我可以为类而不是实例定义 __repr__ 吗? [复制]

Posted

技术标签:

【中文标题】我可以为类而不是实例定义 __repr__ 吗? [复制]【英文标题】:Can I define a __repr__ for a class rather than an instance? [duplicate] 【发布时间】:2012-02-15 20:45:53 【问题描述】:

我可以为类而不是实例定义__repr__ 吗?例如,我正在尝试这样做

class A(object):
    @classmethod
    def __repr__(cls):
        return 'My class %s' % cls

我得到的是

In [58]: a=A()

In [59]: a
Out[59]: My class <class '__main__.A'>

In [60]: A
Out[60]: __main__.A

我试图让第 60 行的输出看起来像“我的 A 类”,而不是实例 a。我想这样做的原因是我正在使用 Python 的元类生成很多类。而且我想要一种比股票代表更易读的方式来识别类。

【问题讨论】:

误解了您的问题。发布了另一个(希望是正确的)答案。 【参考方案1】:

您需要在元类上定义__repr__

class Meta(type):
    def __repr__(cls):
        return 'My class %s' % cls.__name__

class A(object):
    __metaclass__ = Meta

__repr__ 返回对象实例的表示。因此,通过在 A 上定义 __repr__,您可以指定您希望 repr(A()) 的外观。

要定义类的表示,您需要定义type 的实例如何表示。在这种情况下,请将 type 替换为自定义元类,并根据需要定义 __repr__

>> repr(A)
My class A

如果您想为每个类定义一个自定义__repr__,我不确定是否有一种特别干净的方法可以做到这一点。但是你可以做这样的事情。

class Meta(type):
    def __repr__(cls):
        if hasattr(cls, '_class_repr'):
            return getattr(cls, '_class_repr')()
        else:
            return super(Meta, cls).__repr__()

class A(object):
    __metaclass__ = Meta

    @classmethod
    def _class_repr(cls):
        return 'My class %s' % cls.__name__

class B(object):
    __metaclass__ = Meta

然后您可以根据每个班级进行自定义。

>> repr(A)
My class A
>> repr(B)
<__main__.B object at 0xb772068c>

【讨论】:

请注意,在 Python 3 中__metaclass__ 没有特殊含义,您应该使用class A(metaclass=Meta) @RobWouters 谢谢 :) 没有意识到已经改变了。 谢谢。有道理。一个问题是 iPython 似乎在做自己的事情,而不是在其 REPL 中使用 repr :( 我正在撤回我的错误答案(将 __builtins__.repr 重新定义为无效)并投票给这个答案。感谢 jsbueno 指出。【参考方案2】:

我可以为类而不是实例定义 __repr__ 吗?

当然,我在这里演示了通过repr 测试的__repr__

class Type(type):
    def __repr__(cls):
        """
        >>> Type('Baz', (Foo, Bar,), '__module__': '__main__', '__doc__': None)
        Type('Baz', (Foo, Bar,), '__module__': '__main__', '__doc__': None)
        """
        name = cls.__name__
        parents = ', '.join(b.__name__ for b in cls.__bases__)
        if parents:
            parents += ','
        namespace = ', '.join(': '.join(
          (repr(k), repr(v) if not isinstance(v, type) else v.__name__)) 
               for k, v in cls.__dict__.items())
        return 'Type(\'0\', (1), 2)'.format(name, parents, namespace)

    def __eq__(cls, other):
        return (cls.__name__, cls.__bases__, cls.__dict__) == (
                other.__name__, other.__bases__, other.__dict__)

并演示:

class Foo(object): pass

class Bar(object): pass

Python 2:

class Baz(Foo, Bar): 
    __metaclass__ = Type

或 Python 3:

class Baz(Foo, Bar, metaclass=Type): 
    pass

或者相当普遍:

Baz = Type('Baz', (Foo, Bar), )
>>> Baz
Type('Baz', (Foo, Bar,), '__module__': '__main__', '__doc__': None)

并进行repr 测试:

def main():
    print Baz
    assert Baz == eval(repr(Baz))

repr 测试是什么?这是repr文档中的上述测试:

>>> help(repr)
Help on built-in function repr in module __builtin__:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

【讨论】:

以上是关于我可以为类而不是实例定义 __repr__ 吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

可以在python中更改函数的repr吗?

元类的类 __repr__,而不是类

Python详解类的 __repr__() 方法

python学习之__str__,__repr__

Python __repr__ 用于所有成员变量

Python3基础 __repr__ 类的实例对象的名字 可以打印文字