__str__
和 __repr__
在 Python 中有什么区别?
原文由 Casebash 发布,翻译遵循 CC BY-SA 4.0 许可协议
__str__
和 __repr__
在 Python 中有什么区别?
原文由 Casebash 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.2k 阅读✓ 已解决
2 回答862 阅读✓ 已解决
1 回答1.7k 阅读✓ 已解决
亚历克斯 总结得很好,但令人惊讶的是,他过于简洁了。
首先,让我重申一下 Alex 帖子中的 要点:
__repr__
目标是明确的__str__
目标是可读__str__
使用包含的对象__repr__
默认实现是无用的
这主要是一个惊喜,因为 Python 的默认值往往相当有用。但是,在这种情况下,默认为
__repr__
其作用如下:会太危险(例如,如果对象相互引用,太容易进入无限递归)。所以 Python 解决了。请注意,有一个默认值是正确的:如果定义了
__repr__
,并且未定义__str__
,则该对象的行为就像__str__=__repr__
这意味着,简单来说:几乎每个您实现的对象都应该有一个功能性的
__repr__
可用于理解该对象。实施__str__
是可选的:如果您需要“漂亮的打印”功能(例如,由报告生成器使用),请执行此操作。__repr__
的目标是明确的让我直接说出来——我不相信调试器。我真的不知道如何使用任何调试器,也从未认真使用过。此外,我认为调试器的最大错误在于它们的基本特性——我调试的大多数故障都发生在很久很久以前,在一个遥远的星系中。这意味着我确实怀着宗教狂热相信伐木。日志记录是任何体面的即发即弃服务器系统的命脉。 Python 使记录变得容易:也许有一些项目特定的包装器,你所需要的只是一个
但是你必须做最后一步——确保你实现的每个对象都有一个有用的 repr,这样这样的代码才能正常工作。这就是为什么出现“评估”的原因:如果您有足够的信息
eval(repr(c))==c
,这意味着您知道关于c
的所有信息。如果这足够简单,至少以一种模糊的方式,那就去做吧。如果没有,请确保您有足够的关于c
的信息。我通常使用类似 eval 的格式:"MyClass(this=%r,that=%r)" % (self.this,self.that)
。这并不意味着您实际上可以构造 MyClass,或者那些是正确的构造函数参数——但它是一种有用的形式来表达“这是您需要了解的有关此实例的所有信息”。注意:我在上面使用
%r
,而不是%s
。您总是想在 --- 中使用repr()
[或%r
格式化字符,等同于]__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__
这似乎令人惊讶,不是吗?它有点小,但如果它使用他们的
__str__
,它的可读性如何?不是特别的。具体来说,容器中的字符串会发现很容易干扰其字符串表示。面对歧义,请记住,Python 抵制猜测的诱惑。如果您在打印列表时想要上述行为,只需
(您可能还可以弄清楚如何处理字典。
概括
为您实现的任何类实现
__repr__
。这应该是第二天性。实施__str__
如果您认为拥有一个在可读性方面出错的字符串版本会很有用。