代码之家  ›  专栏  ›  技术社区  ›  Daniel Stutzbach Edward Leno

如何在python中处理recursive repr()?

  •  12
  • Daniel Stutzbach Edward Leno  · 技术社区  · 15 年前

    我已经用python编写了一个容器类型,并尝试编写一个健壮的 __repr__ 方法,该方法正确处理容器包含自身的情况。

    例如,下面是内置的 list 做:

    >>> x = []
    >>> x.append(x)
    >>> repr(x)
    '[[...]]'
    

    用c for cpython编写的容器类型可以通过使用 Py_ReprEnter Py_ReprLeave . 纯Python中是否有同等的功能,或者我是否需要创建自己的功能?

    2 回复  |  直到 13 年前
        1
  •  7
  •   bobince    15 年前

    你可以创建自己的,但是如果你想正确地做这件事会有点痛苦:你不应该在对象本身存储一个Being-Repr'd标记标志,因为这不是线程安全的。相反,您可以存储一个线程本地实例集,这些实例将被重复。

    一个更便宜的解决方案是依靠内置的 repr 它处理递归,例如:

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

    只要 递归循环中的对象导致 Py_ReprEnter 发生, 再PR 无法形成完整的循环。

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

    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)
    
        2
  •  5
  •   hwiechers    13 年前

    如果您使用的是python 3,那么可以使用 reprlib.recursive_repr 装饰者。