【问题标题】:Python __str__ - can it be ambiguous?Python __str__ - 它会模棱两可吗?
【发布时间】:2021-04-17 01:59:13
【问题描述】:

__str__ 可以返回任何我灵魂渴望的东西吗?

__str__ 上的文档指出:

[...] 对象的“非正式”或可打印的字符串表示

应该如何解读?

  • A.只要我认为它代表对象,它就可以返回任何东西。
  • 乙。它应该返回对象的明确表示,尽管它可以按我喜欢的任何方式进行格式化。

A 示例:

class Vehicle:
    def __init__(self, owner):
        self.owner = owner
        self.wheels = 4
    def __str__(self):
        return "%s with %s wheels" % (self.owner, self.wheels)
print(Vehicle('Benjamin'))
>>> Benjamin with 4 wheels

B 示例:

class Vehicle:
    def __init__(self, owner):
        self.owner = owner
        self.wheels = 4
    def __str__(self):
        return "Vehicle, owner is %s, with %s wheels" % (self.owner, self.wheels)
print(Vehicle('Benjamin'))
>>> Vehicle, owner is Benjamin, with 4 wheels

我发现的几乎所有资源(123456)都表明输出 - 虽然它可以是非正式的 - 应该是明确和明确的(这是有道理的:Explicit is better than implicit., Readability counts. In the face of ambiguity, refuse the temptation to guess.)。

但是,鉴于文档中的“非正式”一词,有一些建议实际上可能是模棱两可和隐含的(12)。我发现一位开发人员表示可以使用__str__ 中对象的任何表示,而__repr__ 用于明确和明确的表示。我想了解他们的观点,但找不到任何支持他们的理由。您能否建议应该如何解释该文档并支持您的推理?

【问题讨论】:

  • __repr__ 应返回可用于重新构造完全相同的对象的有效文字。 __str__ 可以是您想要的任何东西,但显然最好与您的对象有关。您不应将__str__ 与用于更复杂格式的单独模板混淆;您可能希望在许多不同的情况下使用您的对象,因此在其__str__ 方法中硬编码一种模板并不太有用。
  • 感谢您的回答!您能否提供一些来源或扩展您说“__str__ 可以是您想要的任何东西”背后的逻辑?文档似乎没有这样说——恰恰相反,它应该是对象的表示(不是说它“应该最好与它有关”)——这就是为什么我想知道一个人怎么会说它可以是“你想要的任何东西”
  • 文档很清楚__str__ 可以返回任何你认为合适的东西(只要它是一个字符串)。请注意,即使__repr__ 的文档被认为是“更严格”的版本,也不是非常严格,它说明了“如果可能的话”之类的内容。不要想太多。
  • 感谢您的想法 Juanpa 并鼓励不要过度考虑这一点,但文档说明的情况恰恰相反,不是吗? “对象的表示”并不完全是“您认为合适的任何东西”。查看动词“代表”的定义可以清楚地表明,并非所有事情都可以,但返回的字符串需要符合特定的假设。如果我从Vehicle.__str__ 返回'MyObject',那会是正确的实现吗?

标签: python oop object debugging logging


【解决方案1】:

问题是如何使用这些东西。作为如何使用__str__ 的示例,请查看Django's admin interface。只需注册一个模型类,它就会围绕它生成一个功能齐全的管理界面。默认情况下,在此类模型对象的列表中,对象使用其__str__ 表示表示(这可以进一步自定义,但这是合理的默认设置)。因此,__str__ 应该返回一个在管理界面中有意义的表示。它不应该太冗长,不应该是一个句子,但它应该唯一地标识对象。

因此,如何以有用的方式唯一标识对象取决于它的确切含义和您的应用程序。假设您有一个博客应用程序,那么对于识别其中的每篇文章,这样的内容可能最有用:

def __str__(self):
    return f'{self.id} — {self.title}'

这完全取决于您和您的用例,但大多数情况下它应该是对人类有用的东西__str__ 表示没有程序化使用,因此 Python 并不特别关心或规定它必须遵守的任何特定格式。

__repr__ 应该,如果可能的话,返回一个允许你重构确切对象的字面量。这主要是为开发人员准备的,并且可以极大地帮助调试。如果您执行print(things) 之类的操作并得到以下信息:

[<__main__.Thing object at 0x818745692312>]

这只会为您提供最少的信息,而不会提供更多信息。如果自定义__repr__

def __repr__(self):
    return f'{type(self).__name__}(foo={self.foo!r})'

...您的列表现在打印如下:

[Thing(foo='bar')]

现在您可以将其直接复制粘贴到 Python shell 中,并进一步使用它来重现问题并进一步调试。这就是它的用途,正确使用它可以简化您的开发。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多