4 回答
TA贡献1966条经验 获得超4个赞
首先,让我重申Alex的帖子中的要点:
默认实现是无用的(很难想到一个不会,但是是的)
__repr__
目标是明确的__str__
目标是可读的容器的
__str__
用途包含对象'__repr__
默认实现是无用的
这主要是一个惊喜,因为Python的默认值往往非常有用。但是,在这种情况下,具有默认值的__repr__
行为如下:
return "%s(%r)" % (self.__class__, self.__dict__)
本来就太危险了(例如,如果对象相互引用,太容易进入无限递归)。所以Python警察出来了。请注意,有一个默认值为true:如果__repr__
已定义,而__str__
不是,则该对象的行为就像是一样__str__=__repr__
。
这意味着,简单来说:您实现的几乎每个对象都应具有__repr__
可用于理解对象的功能。实现__str__
是可选的:如果您需要“漂亮打印”功能(例如,由报告生成器使用),请执行此操作。
目标__repr__
是明确无误
让我直接说出来 - 我不相信调试器。我真的不知道如何使用任何调试器,并且从未认真使用过。此外,我认为调试器的大错是它们的基本性质 - 我调试的大多数失败发生在很久很久以前,在一个遥远的星系中。这意味着我确实相信,在宗教热情的情况下,伐木。记录是任何体面的即发即弃服务器系统的生命线。Python可以很容易地记录:可能有一些项目特定的包装器,你需要的只是一个
log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)
但是你必须做最后一步 - 确保你实现的每个对象都有一个有用的repr,所以这样的代码可以正常工作。这就是“eval”事情出现的原因:如果你有足够的信息eval(repr(c))==c
,那就意味着你知道所有要知道的事情c
。如果这很容易,至少以模糊的方式,做到这一点。如果没有,请确保您有足够的信息c
。我通常使用类似eval的格式:"MyClass(this=%r,that=%r)" % (self.this,self.that)
。这并不意味着你可以实际构造MyClass,或者那些是正确的构造函数参数 - 但它是一种有用的形式来表达“这是你需要了解的关于这个实例的一切”。
注意:我%r
上面使用过,不是%s
。你总是希望在实现中使用repr()
[或%r
格式化字符,等效] __repr__
,或者你正在击败repr的目标。你希望能够区分MyClass(3)
和MyClass("3")
。
目标__str__
是可读性
具体来说,它并不是明确的 - 请注意str(3)==str("3")
。同样,如果你实现了一个IP抽象,它的str看起来像192.168.1.1就好了。在实现日期/时间抽象时,str可以是“2010/4/12 15:35:22”等。目标是以用户而不是程序员想要读取它的方式来表示它。砍掉无用的数字,假装是其他类 - 只要它支持可读性,它就是一种改进。
容器的__str__
用途包含对象'__repr__
这似乎令人惊讶,不是吗?它有点,但可读性如何
[moshe is, 3, hello world, this is a list, oh I don't know, containing just 4 elements]
是?不是特别的。具体来说,容器中的字符串会发现太容易打扰它的字符串表示。面对模棱两可,请记住,Python抵制猜测的诱惑。如果您在打印列表时想要上述行为,请执行
print "[" + ", ".join(l) + "]"
(你也可以弄清楚如何处理词典。
摘要
实现__repr__
您实现的任何类。这应该是第二天性。实现__str__
,如果你认为这将是具有犯错可读性侧面的字符串版本是有用的。
TA贡献1890条经验 获得超9个赞
除非您特别采取行动以确保其他方面,否则大多数课程都没有任何有用的结果:
>>> class Sic(object): pass... >>> print str(Sic())<__main__.Sic object at 0x8b7d0>>>> print repr(Sic())<__main__.Sic object at 0x8b7d0>>>>
如你所见 - 没有区别,也没有超出类和对象的信息id
。如果你只覆盖其中一个......:
>>> class Sic(object): ... def __repr__(object): return 'foo'... >>> print str(Sic())foo>>> print repr(Sic())foo>>> class Sic(object):... def __str__(object): return 'foo'... >>> print str(Sic())foo>>> print repr(Sic())<__main__.Sic object at 0x2617f0>>>>
如你所见,如果你覆盖__repr__
,那也是用于__str__
,但反之亦然。
要知道的其他重要花絮:__str__
在内置容器上使用__repr__
,而不是__str__
它包含的项目。而且,尽管在典型的文档中找到了关于主题的文字,但几乎没有人会把__repr__
对象变成一个eval
可能用来构建一个平等对象的字符串(它太难了,而且不知道相关模块是如何实际导入的完全不可能)。
因此,我的建议是:专注于制作__str__
合理的人类可读性,并__repr__
尽可能明确无误,即使这会干扰模糊的无法实现的目标,__repr__
即将返回值作为输入来接受__eval__
!
添加回答
举报