`__repr__`函数对正常函数的意义是什么?

时间:2015-08-05 05:37:31

标签: python python-2.7

我正在尝试用自己的python学习python而且我坚持__repr__函数。虽然我已经在__repr__上阅读了很多关于python文档的帖子。所以我决定在这里提出这个问题。下面的代码解释了我的困惑。

class Point:

    def __init__(self,x,y):
            self.x, self.y = x,y

    def __repr__(self):
        return 'Point(x=%s, y=%s)'%(self.x, self.y)

    def print_class(self):
        return 'Point(x=%s, y=%s)'%(self.x, self.y)



p = Point(1,2)

print p
print p.print_class()


Point(x=1, y=2)
Point(x=1, y=2)

如果正常函数也可以执行类似的任务,那么__repr__优于print_class()(在我的情况下是正常函数)函数的额外优势是什么。

3 个答案:

答案 0 :(得分:5)

__repr__函数在内部由repr()调用。直接打印对象时会调用repr(),而类不会定义__str__()。来自documentation -

  

<强>对象.__再版__(个体)

     

由repr()内置函数和字符串转换(反向引号)调用,以计算对象的“官方”字符串表示形式。如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象(给定适当的环境)。如果这不可能,则形式为&lt; ...一些有用的描述的字符串...&gt;应该退还。返回值必须是字符串对象。如果一个类定义__repr__()但不定义__str__(),那么当需要该类的实例的“非正式”字符串表示时,也会使用__repr__()

print_class()的情况下,您必须在打印对象时专门调用该方法。但是在__repr__()的情况下,print会内部调用它。

当您混合不同的类/类型时,这尤其有用。例如,我们可以列出一个列表,其中包含point类的数字和对象,现在您要打印列表中的元素。

如果您没有定义__repr__()__str__(),则必须首先检查实例,是否为Point类型,如果是,请调用print_class(),或者不要直接打印号码。

但是,当您的班级定义__repr__()__str__()时,您可以直接在列表的所有元素上调用printprint语句将在内部处理打印正确的值。

示例,让我们假设一个类具有print_class()方法,但没有__repr__()__str__(),代码 -

>>> class CA:
...     def __init__(self,x):
...             self.x = x
...     def print_class(self):
...             return self.x
...
>>> l = [1,2,3,CA(4),CA(5)]
>>> for i in l:
...     print(i)
...
1
2
3
<__main__.CA object at 0x00590F10>
<__main__.CA object at 0x005A5070>
SyntaxError: invalid syntax
>>> for i in l:
...     if isinstance(i, CA):
...             print(i.print_class())
...     else:
...             print(i)
...
1
2
3
4
5

正如您所看到的,当我们在列表中混合CA类型的数字和对象,然后当我们刚刚执行print(i)时,它没有打印出我们想要的内容。为了使其正常工作,我们必须检查i的类型并调用适当的方法(如第二种情况所示)。

现在让我们假设一个实现__repr__()而不是print_class() -

的类
>>> class CA:
...     def __init__(self,x):
...             self.x = x
...     def __repr__(self):
...             return str(self.x)
...
>>>
>>> l = [1,2,3,CA(4),CA(5)]
>>> for i in l:
...     print(i)
...
1
2
3
4
5

正如您在第二种情况中所看到的那样,只需打印就可以了,因为print首先在内部调用__str__(),而且不存在则回到__repr__()

不仅如此,当我们执行str(list)时,内部会调用每个列表的元素__repr__()。示例 -

第一种情况(没有__repr__()) -

>>> str(l)
'[1, 2, 3, <__main__.CA object at 0x005AB3D0>, <__main__.CA object at 0x005AB410>]'

第二种情况(__repr__()) -

>>> str(l)
'[1, 2, 3, 4, 5]'

此外,在交互式解释器中,当您直接使用该对象时,它会显示repr()函数的输出,示例 -

>>> class CA:
...     def __repr__(self):
...             return "CA instance"
...
>>>
>>> c = CA()
>>> c
CA instance

答案 1 :(得分:3)

不同之处在于,__repr__函数在某些上下文中由Python自动调用,并且是具有特定要求的预定义API的一部分。例如,如果您在创建p对象后在交互式shell中单独输入print p(而不是p),则会调用其__repr__。如果您未在print p上定义__str__,它也将用于p。 (也就是说,您必须编写print p.print_class(),但您不必编写print p.__repr__(); Python会自动为您调用__repr__。)描述__repr__的要求在the documentation中:

  

由repr()内置函数和字符串转换(反向引号)调用,以计算对象的“官方”字符串表示形式。如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象(给定适当的环境)。如果这不可能,则形式为&lt; ...一些有用的描述的字符串...&gt;应该退还。

简而言之,如果您编写自己的方法print_class,您可以让它做任何您想做的事情并告诉人们如何使用它,因为它是您的API。如果你使用__repr__,你应该遵循Python API的约定。根据具体情况,任何一个都可能有意义。

答案 2 :(得分:0)

它可以帮助您进行更有效的编码工作。即使您使用'print_class()'等用户定义方法作为 repr 获得相同的结果,但您不需要通过 repr 输入'.print_class()'方法