定义类的 repr()(不是实例)

Alf*_*lfe 3 python debugging class instance

我有一堆类用作单例/枚举/字典键,例如:

class Side(object): pass

class Left(Side): pass
class Right(Side): pass

def show_state(distribution):
    print "left is", distribution[Left]
    print "right is", distribution[Right]

distribution = { Left: 3, Right: 7 }
show_state(distribution)
Run Code Online (Sandbox Code Playgroud)

这对我来说很好用。但是我有时会遇到调试输出的小问题。通常我只使用print在这个喜欢print distributionshow_state()功能。我希望有这样的输出:

{ Left: 3, Right: 7 }
Run Code Online (Sandbox Code Playgroud)

但是当我用这些类来做这件事时,它们是这样给出的:

{<class '__main__.Right'>: 7, <class '__main__.Left'>: 3}
Run Code Online (Sandbox Code Playgroud)

我试图覆盖__repr__()我的类的方法来实现这一点,但是当我这样做时,它只会影响我的类的实例(我从未创建过)。我尝试使用@classmethod@staticmethod但没有任何效果。

我假设我打印的是一个Left,因此是 的实例<type 'type'>,因此不幸的是,我必须覆盖不可变__repr__()type类的方法。

我可以使用任何其他技巧print distribution来打印我想要的东西吗?

顺便说一句,根据文档,该__repr__()方法应该返回 Python 解析器将再次变成相等对象的内容;像这样的输出绝对不是这种情况,<class '__main__.Right'>但像Right.

Mar*_*ers 5

你是正确的,你必须覆盖__repr__一个类的类型;你不需要编辑type,你子类 type来创建一个新的元类

class SimpleRepr(type):
    def __repr__(cls):
        return cls.__name__
Run Code Online (Sandbox Code Playgroud)

然后将其用作您的类元类;假设您使用的是 Python 3:

class Side(metaclass=SimpleRepr): pass
Run Code Online (Sandbox Code Playgroud)

或者如果您仍在使用 Python 2:

class Side(object):
    __metaclass__ = SimpleRepr
Run Code Online (Sandbox Code Playgroud)

Side类也继承元类:

>>> class SimpleRepr(type):
...     def __repr__(cls):
...         return cls.__name__
...
>>> class Side(metaclass=SimpleRepr): pass
...
>>> class Left(Side): pass
...
>>> class Right(Side): pass
...
>>> { Left: 3, Right: 7 }
{Left: 3, Right: 7}
Run Code Online (Sandbox Code Playgroud)

但是,您可以只使用实例:

class Side(object):
    __slots__ = ('name',)
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return self.name

Left = Side('Left')
Right = Side('Right')
Run Code Online (Sandbox Code Playgroud)