【问题标题】:Python object.__repr__(self) should be an expression?Python object.__repr__(self) 应该是一个表达式?
【发布时间】:2009-01-16 22:37:18
【问题描述】:

我正在查看Python documentation 中的内置对象方法,我对object.__repr__(self) 的文档很感兴趣。它是这样说的:

由 repr() 内置函数调用 并通过字符串转换(反向 报价)来计算“官方” 对象的字符串表示。如果 在所有可能的情况下,这应该看起来像 一个有效的 Python 表达式,它可以 用于重新创建一个对象 相同的值(给定一个适当的 环境)。如果这是不可能的, <...> 应该返回。 返回值必须是字符串 目的。如果一个类定义了 repr() 但不是 str(),那么 repr() 是 也用于“非正式”字符串 该实例的表示 类是必需的。

这通常用于调试, 所以重要的是 表示是信息丰富的, 明确的

对我来说最有趣的部分是......

如果可能的话,这应该看起来像一个有效的 Python 表达式,可用于重新创建具有相同值的对象

...但我不确定这到底是什么意思。它说它应该看起来像一个可用于重新创建对象的表达式,但这是否意味着它应该只是你可以使用的那种表达式的一个例子,或者它应该是一个实际的表达式,可以执行(eval 等)来重新创建对象?或者......是否应该只是为了纯粹的信息目的而对所使用的实际表达进行重新设计?

总的来说,我对我应该在这里放什么感到有点困惑。

【问题讨论】:

标签: python


【解决方案1】:
>>> from datetime import date
>>>
>>> repr(date.today())        # calls date.today().__repr__()
'datetime.date(2009, 1, 16)'
>>> eval(_)                   # _ is the output of the last command
datetime.date(2009, 1, 16)

输出是一个字符串,可以被python解释器解析并产生一个相等的对象。

如果不可能,它应该以&lt;...some useful description...&gt; 的形式返回一个字符串。

【讨论】:

  • 请注意尝试让您的 __repr__() 生成一个返回对象副本的表达式的缺点:您必须假设原始包已完全导入。如果您只运行 Georg 的三行代码,您将得到“NameError: name 'datetime' is not defined”,因为从未导入过 datetime 包。仅导入了“datetime”中的“date”。
【解决方案2】:

要查看 repr 在类中的工作方式,请运行以下代码,先使用 repr 方法,然后再不使用方法。

class Coordinate (object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def getX(self):
        # Getter method for a Coordinate object's x coordinate.
        # Getter methods are better practice than just accessing an attribute directly
        return self.x
    def getY(self):

        # Getter method for a Coordinate object's y coordinate
        return self.y

    def __repr__(self):  #remove this and the next line and re-run
        return 'Coordinate(' + str(self.getX()) + ',' + str(self.getY()) + ')' 

>>>c = Coordinate(2,-8)
>>>print(c)

【讨论】:

  • 我更新了__repr__函数,将return 'Coordinate(' + str(self.getX()) + ',' + str(self.getY()) + ')'替换为return 'Coordinate({},{})'.format(self.getX(), self.getX())
【解决方案3】:

'repr' 表示表示。 首先,我们创建一个类坐标的实例。

x = Coordinate(3, 4) 

那么如果我们在控制台输入x,输出是

<__main__.Coordinate at 0x7fcd40ab27b8>

如果你使用 repr():

>>> repr(x)
Coordinate(3, 4)

输出与 'Coordinate(3, 4)' 相同,除了它是一个字符串。您可以使用它来重新创建坐标实例。

总之,repr()方法就是打印出一个字符串,就是对象的表示。

【讨论】:

    【解决方案4】:

    指南:如果您可以简洁地提供精确表示将其格式化为 Python 表达式(这意味着它可以是 eval 'd 并在正确的上下文中直接复制到源代码中)。如果提供不精确的表示使用&lt;...&gt; 格式

    任何值都有许多可能的表示形式,但 Python 程序员最感兴趣的一种是重新创建值的表达式。请记住,了解 Python 的人是目标受众——这也是为什么不精确的表示应该包含相关上下文的原因。即使是默认的&lt;XXX object at 0xNNN&gt;,虽然几乎完全没用,但仍然提供类型id()(用于区分不同的对象),并表明没有更好的表示可用。

    【讨论】:

      【解决方案5】:

      它应该是一个 Python 表达式,当 eval'd 时,它会创建一个与这个具有完全相同属性的对象。例如,如果您有一个 Fraction 类,其中包含两个整数、一个分子和一个分母,那么您的 __repr__() 方法将如下所示:

      # in the definition of Fraction class
      def __repr__(self):
          return "Fraction(%d, %d)" % (self.numerator, self.denominator)
      

      假设构造函数采用这两个值。

      【讨论】:

        【解决方案6】:

        “但这是否意味着它应该只是您可以使用的那种表达式的示例,或者它应该是一个可以执行(eval 等)以重新创建对象的实际表达式?或者...是否应该只是为了纯粹的信息目的而对所使用的实际表达进行重新设计?”

        哇,真费劲。

        1. “您可以使用的那种表达方式的示例”不会是特定对象的表示。那不可能是有用的或有意义的。

        2. “可以……重新创建对象的实际表达式”和“对用于 [创建对象] 的实际表达式的重新定义”之间有什么区别?两者都是创建对象的表达式。这些之间没有实际区别。 repr 调用可以生成新表达式或原始表达式。在许多情况下,它们是相同的。

        请注意,这并不总是可行、实用或理想的。

        在某些情况下,您会注意到 repr() 提供的字符串显然不是任何类型的表达式。您定义的任何类的默认 repr() 都不能用作表达式。

        在某些情况下,对象之间可能存在相互(或循环)引用。那种错综复杂的层次结构的 repr() 是没有意义的。

        在许多情况下,对象是通过解析器增量构建的。例如,来自 XML 或 JSON 之类的。代表会是什么?原始 XML 还是 JSON?显然不是,因为它们不是 Python。它可能是一些生成 XML 的 Python 表达式。但是,对于一个巨大的 XML 文档,可能无法编写一个与解析 XML 功能等效的 Python 表达式。

        【讨论】:

        • 这就是为什么:如果这不可能(创建一个有效的 Python 表达式),应该返回一个 <...> 形式的字符串。如果您无法提供可以直接转换为代码的字符串,只需在“<...>”中提供有用的描述。
        【解决方案7】:

        我认为这里的混乱源于英语。我的意思是__repr__();我猜测的值的“表示”的缩写,就像@S.Lott 所说的

        ““一个可以...重新创建对象的实际表达式”和“对用于[创建对象]的实际表达式的重新定义”之间有什么区别?两者都是创建对象的表达式. 它们之间没有实际区别。repr 调用可以生成新表达式或原始表达式。在许多情况下,它们是相同的。"

        但在某些情况下,它们可能会有所不同。例如;坐标点,您可能希望 c.coordinate 返回:3,5c.__repr__ 返回 Coordinate(3, 5)。希望这更有意义......

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-24
          相关资源
          最近更新 更多