我在Python中编写了一个容器类型,我正在尝试编写一个健壮的__repr__
方法,该方法可以正确处理容器包含自身的情况。
例如,这是内置list
的作用:
>>> x = []
>>> x.append(x)
>>> repr(x)
'[[...]]'
使用C语言为CPython编写的容器类型可以使用Py_ReprEnter
和Py_ReprLeave
来实现此功能。在纯Python中是否有相同的功能,或者我是否需要创建自己的功能?
答案 0 :(得分:7)
你可以创建自己的,但是如果你想要正确地做到这一点有点痛苦:你不应该在对象本身上存储'正在重新标记'标记,因为那不是线程安全的。相反,您可以存储正在重新创建的线程本地实例集。
更便宜的解决方案是依赖于负责递归的内置repr
,例如:
def __init__(self, *list):
self._list= list
def __repr__(self):
return 'mything('+repr(self._list)[1:-1]+')')
只要递归循环中的一个对象导致Py_ReprEnter
发生,repr
就无法形成完整的循环。
如何创建线程本地实例集?
使用threading模块:
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)
答案 1 :(得分:5)
如果您使用的是Python 3,则可以使用reprlib.recursive_repr装饰器。