5

作为关于状态的 Python 2 文档__repr__

如果可能的话, this (ie __repr__) 应该看起来像一个有效的 Python 表达式,可用于重新创建具有相同值的对象(给定适当的环境)。

那么为什么内置__repr__的类不符合该准则呢?

例子

>>> class A(object):
...   pass
>>> repr(A)
"<class 'A'>"

为了符合准则,默认__repr__应该返回"A",即一般A.__name__。为什么表现不一样?我相信这将非常容易实施。


编辑:“复制”的范围

我可以在答案中看到,在讨论中不清楚repr应该返回什么。在我看来,该repr函数应该返回一个允许您重现对象的字符串:

  1. 在任意上下文
  2. 自动(即不是手动)。

广告1。看看一个内置的类案例(取自这个 SO question):

>>> from datetime import date
>>>
>>> repr(date.today())        # calls date.today().__repr__()
'datetime.date(2009, 1, 16)'

显然,假设的上下文就好像您使用导入的基本形式,即import datetime,因为如果您尝试eval(repr(date.today()))datetime将不会被识别。所以重点是__repr__不需要从头开始表示对象。如果它在社区同意的上下文中是明确的就足够了,例如使用直接模块的类型和功能。听起来很合理,对吧?

广告 2。repr我相信,仅仅给出一个物体如何被重建的印象是不够的。有助于调试是str.

结论

所以我期望的repr是允许我对eval结果做些什么。对于一个类,我不想获得从头开始重建类的整个代码。相反,我希望明确引用在我的范围内可见的类。"Module.Class"就足够了。没有冒犯,Python,但"<class 'Module.Class'>"不只是削减它。

4

4 回答 4

2

考虑一个稍微复杂的类:

class B(object):
    def __init__(self):
        self.foo=3

repr需要返回类似的东西

type("B", (object,), { "__init__": lambda self: setattr(self, "foo", 3) })

已经注意到一个困难:并非所有由def语句定义的函数都可以转换为单个lambda表达式。B稍作改动:

class B(object):
    def __init__(self, x=2, y, **kwargs):
        print "in B.__init__"

你如何写一个定义的表达式B.__init__?你不能使用

lambda self: print "in B.__init__"

因为lambda表达式不能包含语句。对于这个简单的类,编写一个完整定义该类的表达式已经是不可能的了。

于 2013-03-12T13:31:51.693 回答
1

因为默认__repr__ 无法知道创建类时使用了哪些语句。

您引用的文档以If at all possible开头。由于无法以允许您重新创建自定义类的方式表示自定义类,因此使用了不同的格式,该格式遵循所有不易重新创建的事物的默认值。

如果repr(A)只是返回'A',那将毫无意义。你不是在重新创建A,你只是在引用它。"type('A', (object,), {})"会更接近于反映类构造函数,但这会 a) 让不熟悉 python 类是实例的人感到困惑,type并且 b) 永远无法准确地反映方法和属性。

将输出与的输出进行比较,repr(type)或者repr(int)相反,它们遵循相同的模式。

于 2013-03-12T13:12:57.187 回答
1

我知道这是一个较老的问题,但我找到了一种方法。

我知道这样做的唯一方法是使用这样的元类:

class A(object):
    secret = 'a'

    class _metaA(type):
        @classmethod
        def __repr__(cls):
            return "<Repr for A: secret:{}>".format(A.secret)
    __metaclass__ =_metaA

输出:

>>> A
<Repr for A: secret:a>
于 2017-03-21T20:22:40.147 回答
0

由于在定义不可用时既"<class 'A'>"不能也"A"不能用于重新创建类,我认为这个问题没有实际意义。

于 2013-03-12T13:12:14.630 回答