我能为一个类定义__repr__而不是实例吗?

14

我能为一个类定义__repr__而不是实例吗?例如,我正在尝试做到这一点

可以在类中定义__repr__方法。这样,在创建类的实例时,该方法将被继承并用于表示该实例。例如:


class MyClass:
    def __repr__(self):
        return "MyClass()"

print(MyClass())  # 输出: MyClass()
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行的输出看起来像"My Class A",而不是实例a。我这样做的原因是我正在使用Python元类生成很多类,并且我希望有一种更易读的方式来标识类,而不是使用默认的repr()函数。

误解了你的问题。发布了另一个(希望正确的)答案。 - Michael Mior
2个回答

20

您需要在元类上定义__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>

5
请注意,在Python 3中,__metaclass__没有特殊的意义,而应该使用class A(metaclass=Meta) - Rob Wouters
@RobWouters 谢谢 :) 没想到那个已经改变了。 - Michael Mior
谢谢。那很有道理。一个问题是iPython似乎在REPL中做自己的事情,而不是使用repr。:( - Wai Yip Tung
我撤回了我的错误答案(将__builtins__.repr重新定义为不起作用),并改投这个答案。感谢jsbueno指出。 - Roman Susi

3
我可以为一个类定义 __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.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接