在Python中 __str__和__repr__之间的区别


在Python中 __str____repr__之间的区别

  • 默认实现是无用的
  • __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__,如果你认为这将是具有抱错有利于更多的不确定性的更多可读性一侧的字符串版本是有用的。