如何使用pprint打印对象的内置__str__(self)方法?

22 投票
6 回答
42600 浏览
提问于 2025-04-17 12:17

我有一个Python脚本,它会处理一个包含报告使用信息的.txt文件。我想找到一种方法,使用pprint的pprint(vars(object))函数,干净利落地打印一个对象的属性。

这个脚本会读取文件,并创建一个名为Report的类的实例。下面是这个类的代码。

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)))

我希望能够像使用pprint那样,干净地打印Report的实例。

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

当我调用

print record

来处理一个Report的实例时,终端显示的内容是这样的。

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

我有两个问题。

首先,这种打印对象属性的方式是否好?有没有更好的方法可以使用,或者不使用pprint?

其次,为什么

None

在最后会打印到终端?我对这个有点困惑。

谢谢任何建议。

6 个回答

14

pprint.pprint 这个函数并不会返回一个字符串;它实际上是直接打印内容的(默认是打印到标准输出,也就是屏幕上,但你可以指定其他输出位置)。所以当你写 print record 的时候,其实是调用了 record.__str__(),这个方法又会调用 pprint,而 pprint 返回的是 None。而 str(None) 的结果是 'None',所以最后就打印出了 None

你应该使用 pprint.pformat 来代替这个方法。(另外,你也可以把一个 StringIO 的实例传给 pprint。)

38

Dan的解决方案是错误的,而Ismail的解决方案是不完整的。

  1. __str__()这个方法没有被调用,实际上调用的是__repr__()
  2. __repr__()应该返回一个字符串,就像pformat那样。
  3. 正常情况下,打印出来的内容只会缩进一个字符,并且会尽量节省行数。如果你想要看清楚结构,可以把宽度设置得小一些,缩进设置得大一些。

这里有一个例子

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)

这段代码打印出来的结果是

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

虽然不是完美的,但还算可以。

7

pprint其实就是另一种打印方式。当你写 pprint(vars(self)) 的时候,它会把变量的内容打印出来,但不会返回任何东西,因为它是一个“空”函数。所以当你把它转换成字符串时,就会把 None(就是 pprint 返回的内容)变成字符串,然后再从最初的打印语句中输出。我的建议是,如果你只用这个功能,可以把你的打印改成 pprint,或者重新定义打印功能。

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

另外一种选择是使用格式化输出:

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()])

希望这对你有帮助。

撰写回答