我如何处理Python中的递归repr()?

Dan*_*ach 12 python

我在Python中编写了一个容器类型,我正在尝试编写一个可靠的__repr__方法来正确处理容器包含自身的情况.

例如,这是内置的list功能:

>>> x = []
>>> x.append(x)
>>> repr(x)
'[[...]]'
Run Code Online (Sandbox Code Playgroud)

用C语言编写的用于CPython的容器类型可以通过使用Py_ReprEnter和实现此功能Py_ReprLeave.在纯Python中是否有相同的功能,还是我需要创建自己的?

bob*_*nce 7

你可以创建自己的,但是如果你想要正确地做到这一点有点痛苦:你不应该在对象本身上存储一个'被repr'd'标记,因为那不是线程安全的.相反,您可以存储正在重新创建的线程本地实例集.

更便宜的解决方案是依赖于内置repr的递归,例如:

def __init__(self, *list):
    self._list= list
def __repr__(self):
    return 'mything('+repr(self._list)[1:-1]+')')
Run Code Online (Sandbox Code Playgroud)

只要递归循环中的一个对象Py_ReprEnter发生,repr就不能形成完整的循环.

如何创建线程本地实例集?

使用线程模块:

class MyThing(object):
    _local= threading.local()
    _local.reprs= set()

    def __repr__(self):
        reprs= MyThing._local.reprs
        sid= id(self)
        if sid in reprs:
            return 'MyThing(...)'
        try:
            reprs.add(sid)
            return 'MyThing(%r)' % self.something
        finally:
            reprs.remove(sid)
Run Code Online (Sandbox Code Playgroud)


hwi*_*ers 6

如果您使用的是Python 3,则可以使用reprlib.recursive_repr装饰器.