一尘不染

Python-__str__和__repr__之间的区别?

python

__str____repr__有什么不一样?


阅读 652

收藏
2020-02-04

共1个答案

一尘不染

  • 默认的实现是无用的(很难想象有一个不是,但是是的)
  • __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)

但是,你必须做最后一步-确保实现的每个对象都有一个有用的代表,这样的代码才能正常工作。这就是为什么出现“评估”问题的原因:如果你有足够的信息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__

这似乎令人惊讶,不是吗?有点,但是如果使用它们,它们的可读性如何__str__

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

不是特别的。具体而言,容器中的字符串会发现太容易打乱其字符串表示形式。记住,面对歧义,Python抵制了猜测的诱惑。如果你在打印列表时需要上述行为,则只需

print "[" + ", ".join(l) + "]"

(你可能还可以弄清楚如何处理字典。

摘要

实现__repr__你实现任何类。这应该是第二天性。实现__str__,如果你认为这将是具有犯错可读性侧面的字符串版本是有用的。

2020-02-04