自动生成__repr__方法

31 投票
7 回答
13313 浏览
提问于 2025-04-15 11:08

我想要一个简单的方式来表示任何类的内容,比如像这样 { property = value },有没有自动生成 __repr__ 的方法呢?

7 个回答

7

好吧,我试着玩了一下其他人的答案,得到了一个很不错的解决方案:

class data:
    @staticmethod
    def repr(obj):
        items = []
        for prop, value in obj.__dict__.items():
            try:
                item = "%s = %r" % (prop, value)
                assert len(item) < 20
            except:
                item = "%s: <%s>" % (prop, value.__class__.__name__)
            items.append(item)

        return "%s(%s)" % (obj.__class__.__name__, ', '.join(items))

    def __init__(self, cls):
        cls.__repr__ = data.repr
        self.cls = cls

    def __call__(self, *args, **kwargs):
        return self.cls(*args, **kwargs)

你可以把它当作一个装饰器来使用:

@data
class PythonBean:
    def __init__(self):
        self.int = 1
        self.list = [5, 6, 7]
        self.str = "hello"
        self.obj = SomeOtherClass()

这样就能轻松得到一个聪明的 __repr__ 方法:

PythonBean(int = 1, obj: <SomeOtherClass>, list = [5, 6, 7], str = 'hello')

这个方法适用于任何递归类,包括树形结构。如果你在类里面加一个自我引用,比如 self.ref = self,这个函数会尝试(并成功)处理这个问题,大约需要一秒钟。

当然,记得要考虑你的老板——我老板就不喜欢这样的语法糖 ))

15

是的,你可以创建一个叫“AutoRepr”的类,然后让其他所有类都继承这个类:

>>> class AutoRepr(object):
...     def __repr__(self):
...         items = ("%s = %r" % (k, v) for k, v in self.__dict__.items())
...         return "<%s: {%s}>" % (self.__class__.__name__, ', '.join(items))
... 
>>> class AnyOtherClass(AutoRepr):
...     def __init__(self):
...         self.foo = 'foo'
...         self.bar = 'bar'
...
>>> repr(AnyOtherClass())
"<AnyOtherClass: {foo = 'foo', bar = 'bar'}>"

需要注意的是,上面的代码在处理那些直接或间接引用自己的数据结构时,可能会出现问题。作为替代方案,你可以定义一个适用于任何类型的函数:

>>> def autoRepr(obj):
...     try:
...         items = ("%s = %r" % (k, v) for k, v in obj.__dict__.items())
...         return "<%s: {%s}." % (obj.__class__.__name__, ', '.join(items))
...     except AttributeError:
...         return repr(obj)
... 
>>> class AnyOtherClass(object):
...     def __init__(self):
...         self.foo = 'foo'
...         self.bar = 'bar'
...
>>> autoRepr(AnyOtherClass())
"<AnyOtherClass: {foo = 'foo', bar = 'bar'}>"
>>> autoRepr(7)
'7'
>>> autoRepr(None)
'None'

要注意,上面的函数并没有递归定义,这是故意的,正是为了避免之前提到的问题。

40

最简单的方法:

def __repr__(self):
    return str(self.__dict__)

撰写回答