Python object .__ repr __(self)应该是表达式吗?


73

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

由repr()内置函数和字符串转换(反引号)调用以计算对象的“正式”字符串表示形式。如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象(在适当的环境下)。如果无法做到这一点,则应返回格式为<...一些有用的说明...>的字符串。返回值必须是一个字符串对象。如果一个类定义了repr()而不是str(),则当需要该类实例的“非正式”字符串表示形式时,也使用repr()。

这通常用于调试,因此重要的是,表示形式必须信息丰富且明确

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

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

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

总的来说,我对应该在此处输入的内容有些困惑。


23
该问题与MIT的在线6.00.1x:计算机科学概论的官方课程注释有关。
dotancohen 2014年

Answers:


69
>>> 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解释器解析的字符串,并导致一个相等的对象。

如果无法实现,则应以的形式返回字符串<...some useful description...>


6
请注意尝试让__repr __()生成返回对象副本的表达式的缺点:您必须假定原始包已完全导入。如果仅运行Georg的三行,您将得到“ NameError:名称'datetime'未定义”,因为datetime包从未被导入。仅导入了“ datetime”中的“ date”。
Michael Scott Cuthbert

32

它应该是一个Python表达式,在评估时会创建一个具有与此属性完全相同的对象。例如,如果您的Fraction类包含两个整数,即分子和分母,则您的__repr__()方法将如下所示:

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

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


13

准则:如果可以简洁地提供一个精确的表示将其格式化为Python表达式(这意味着它可以是既eval'd和直接复制到源代码,在正确的上下文)。如果提供不精确的表示,请使用<...>format

任何值都有很多可能的表示形式,但是对于Python程序员而言,最有趣的一种表示形式是可重新创建该值的表达式。请记住,那些了解Python的人是目标受众-这也是为什么不精确表示形式应包含相关上下文的原因。即使是default <XXX object at 0xNNN>,尽管几乎完全没有用,但仍提供了类型id()(以区分不同的对象),并指示没有更好的表示可用。


4

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

哇,真是令人费解。

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

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

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

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

在某些情况下,对象之间可能有相互(或循环)引用。纠结的层次结构的repr()毫无意义。

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


这就是为什么:如果不可能(创建有效的Python表达式),则应返回<...一些有用的描述...>形式的字符串。如果您不能提供直接转换为代码的字符串,请在“ <...>”中提供有用的描述。
华莱士·霍瑞

4

“代表”表示代表。首先,我们创建一个类坐标的实例。

x = Coordinate(3, 4) 

然后,如果我们将x输入到控制台,则输出为

<__main__.Coordinate at 0x7fcd40ab27b8>

如果使用repr():

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

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

总之,将repr()肉类打印出一个字符串,它是对象的表示。


2

若要查看repr在类中的工作方式,请先运行以下代码,然后再使用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)

1
我已__repr__通过return 'Coordinate(' + str(self.getX()) + ',' + str(self.getY()) + ')'return 'Coordinate({},{})'.format(self.getX(), self.getX())
helcode '18

0

我认为这里的混乱源于英语。我是说__repr__(); 我正在猜测的值的“表示形式”的缩写,例如@ S.Lott说

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.