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

时间:2012-01-21 18:58:46

标签: python metaprogramming metaclass

我可以为类而不是实例定义__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的元类生成了很多类。我想要一种更可读的方法来识别类而不是股票代理。

2 个答案:

答案 0 :(得分:19)

您需要在元类上定义__repr__

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

class A(object):
    __metaclass__ = Meta

__repr__返回对象实例的表示。因此,通过在__repr__上定义A,您可以指定您想要的内容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>

答案 1 :(得分:0)

  

我可以为类而不是实例定义__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.