2012-02-03 26 views
10

Tôi có một tập lệnh Python xử lý tệp .txt chứa thông tin sử dụng báo cáo. Tôi muốn tìm một cách để in sạch các thuộc tính của một đối tượng bằng cách sử dụng pprint của pprint (vars (đối tượng)) chức năng.Cách sử dụng dấu in để in một đối tượng bằng phương thức __str __ (self) dựng sẵn?

Tập lệnh đọc tệp và tạo các phiên bản của lớp Báo cáo. Đây là lớp học.

class Report(object): 
    def __init__(self, line, headers): 
     self.date_added=get_column_by_header(line,headers,"Date Added") 
     self.user=get_column_by_header(line,headers,"Login ID") 
     self.report=get_column_by_header(line,headers,"Search/Report Description") 
     self.price=get_column_by_header(line,headers,"Price") 
     self.retail_price=get_column_by_header(line,headers,"Retail Price") 

    def __str__(self): 
     from pprint import pprint 
     return str(pprint(vars(self))) 

Tôi muốn có thể in các phiên bản Báo cáo rõ ràng.

for i,line in enumerate(open(path+file_1,'r')): 
    line=line.strip().split("|") 
    if i==0: 
     headers=line 

    if i==1: 
     record=Report(line,headers) 
     print record 

Khi tôi gọi

print record 

cho một trường hợp duy nhất của Báo cáo, đây là những gì tôi nhận được trong vỏ.

{'date_added': '1/3/2012 14:06', 
'price': '0', 
'report': 'some_report', 
'retail_price': '0.25', 
'user': 'some_username'} 
None 

Câu hỏi của tôi là hai lần.

Đầu tiên, đây có phải là cách tốt/mong muốn để in các thuộc tính của đối tượng một cách sạch sẽ không? Có cách nào tốt hơn để làm điều này có hoặc không có dấu vân tay?

Thứ hai, tại sao

None 

in vào vỏ lúc kết thúc? Tôi đang bối rối đến từ đâu.

Cảm ơn mọi mẹo.

+1

mặt lưu ý trong __str__ khi bạn bao gồm từ pprint pprint nhập khẩu, nếu bạn chỉ sử dụng phương pháp này một hoặc hai lần đó là tốt, nhưng đối với một phương pháp thường được sử dụng mô-đun này sẽ được nhập (cường độ tính toán) mỗi khi phương thức được gọi. Tôi nghĩ tốt hơn là bạn nên nhập các mô-đun của mình ở trên cùng. Điều này cũng cải thiện hiệu suất tổng thể trong các kịch bản python. – lukecampbell

+0

@lukecampbell - không đúng về các lần nhập tiếp theo được tính toán chuyên sâu. Khi bạn nhập khẩu, cơ chế sẽ xem xét một dict trong sys.modules để xem nó đã được tải chưa. Nếu có, không có gì khác được thực hiện. Chỉ khi nó không bao giờ được nhập khẩu thì cơ chế import có làm gì khác không. – bgporter

+0

@bgporter: Nếu bạn tạo một đối tượng khác của đối tượng thì sao? –

Trả lời

5

pprint chỉ là một dạng in khác. Khi bạn nói pprint(vars(self)) nó in vars thành stdout và trả về không vì nó là một hàm void. Vì vậy, khi bạn bỏ nó vào một chuỗi nó quay None (trả về bởi pprint) vào một chuỗi mà sau đó được in từ bản in đầu tiên. Tôi khuyên bạn nên thay đổi bản in của mình thành pprint hoặc xác định lại bản in dưới dạng bản in nếu tất cả những gì bạn sử dụng để in.

def __str__(self): 
    from pprint import pprint 
    return str(vars(self)) 

for i,line in enumerate(open(path+file_1,'r')): 
    line = line.strip().split("|") 
    if i == 0: 
     headers = line 
    if i == 1: 
     record = Report(line,headers) 
     pprint record 

Một thay thế là sử dụng một đầu ra định dạng:

def __str__(self): 
    return "date added: %s\nPrice:  %s\nReport:  %s\nretail price: %s\nuser:   %s" % tuple([str(i) for i in vars(self).values()]) 

Hy vọng điều này giúp

+1

Trong khi bạn đã chẩn đoán thất bại chính xác, các giải pháp được đề xuất là tất cả khá clunky; pprint.pformat là thanh lịch hơn nhiều. – Symmetric

11

pprint.pprint không trả lại chuỗi; nó thực sự làm việc in ấn (theo mặc định để stdout, nhưng bạn có thể chỉ định một dòng đầu ra). Vì vậy, khi bạn viết print record, record.__str__() được gọi, gọi số pprint, trả về None. str(None)'None' và được print ed, đó là lý do bạn thấy None.

Thay vào đó, bạn nên sử dụng pprint.pformat. (Hoặc, bạn có thể chuyển một ví dụ StringIO tới pprint.)

3

Đối với đối tượng khá-in có chứa đối tượng khác, vv pprint là không đủ. Hãy thử IPython's lib.pretty, dựa trên mô-đun Ruby.

from IPython.lib.pretty import pprint 
pprint(complex_object) 
11

Giải pháp của Dan hoàn toàn sai và Ismail không đầy đủ.

  1. __str__() không được gọi, __repr__() được gọi.
  2. __repr__() phải trả về một chuỗi, như pformat.
  3. in thường chỉ thụt vào 1 ký tự và cố gắng lưu đường. Nếu bạn đang cố gắng tìm ra cấu trúc, thiết lập chiều rộng thấp và thụt lề cao.

Dưới đây là một ví dụ

class S: 
    def __repr__(self): 
     from pprint import pformat 
     return pformat(vars(self), indent=4, width=1) 

a = S() 
a.b = 'bee' 
a.c = {'cats': ['blacky', 'tiger'], 'dogs': ['rex', 'king'] } 
a.d = S() 
a.d.more_c = a.c 

print(a) 

này in

{ 'b': 'bee', 
    'c': { 'cats': [ 'blacky', 
         'tiger'], 
      'dogs': [ 'rex', 
         'king']}, 
    'd': { 'more_c': { 'cats': [ 'blacky', 
           'tiger'], 
        'dogs': [ 'rex', 
           'king']}}} 

Mà không phải là hoàn hảo, nhưng khá.

3

Tôi nghĩ rằng beeprint là những gì bạn cần.

Chỉ pip install beeprint và thay đổi mã của bạn để:

def __str__(self): 
    from beeprint import pp 
    return pp(self, output=False) 
Các vấn đề liên quan