删除dicts,lists,tuples中的循环引用

Tom*_*Pom 4 python reference circular-reference

我有这个真的如下破解代码将删除任何类型的数据结构的建造出来的循环引用dict,tuplelist对象.

import ast

def remove_circular_refs(o):
    return ast.literal_eval(str(o).replace("{...}", 'None'))
Run Code Online (Sandbox Code Playgroud)

但我不喜欢它有多酷.这可以在不将数据结构转换为字符串表示的情况下完成吗?

这是一个用于测试的示例结构:

doc1 = {
    "key": "value",
    "type": "test1",
}
doc1["self"] = doc1
doc = {
    'tags': 'Stackoverflow python question',
    'type': 'Stackoverflow python question',
}
doc2 = {
    'value': 2,
    'id': 2,
}
remove_circular_refs(doc)
remove_circular_refs(doc1)
remove_circular_refs(doc2)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 6

不要使用字符串转换,不.只需通过遍历数据结构来检测引用:

def remove_circular_refs(ob, _seen=None):
    if _seen is None:
        _seen = set()
    if id(ob) in _seen:
        # circular reference, remove it.
        return None
    _seen.add(id(ob))
    res = ob
    if isinstance(ob, dict):
        res = {
            remove_circular_refs(k, _seen): remove_circular_refs(v, _seen)
            for k, v in ob.items()}
    elif isinstance(ob, (list, tuple, set, frozenset)):
        res = type(ob)(remove_circular_refs(v, _seen) for v in ob)
    # remove id again; only *nested* references count
    _seen.remove(id(ob))
    return res
Run Code Online (Sandbox Code Playgroud)

这涵盖了dict,listtuple,setfrozenset对象; 它会记住所id()看到的每个物体,当它再次被看到它时会被替换掉None.

演示:

>>> doc1 = {
...     "key": "value",
...     "type": "test1",
... }
>>> doc1["self"] = doc1
>>> doc1
{'key': 'value', 'type': 'test1', 'self': {...}}
>>> remove_circular_refs(doc1)
{'key': 'value', 'type': 'test1', 'self': None}
>>> doc2 = {
...     'foo': [],
... }
>>> doc2['foo'].append((doc2,))
>>> doc2
{'foo': [({...},)]}
>>> remove_circular_refs(doc2)
{'foo': [(None,)]}
>>> doc3 = {
...     'foo': 'string 1', 'bar': 'string 1',
...     'ham': 1, 'spam': 1
... }
>>> remove_circular_refs(doc3)
{'foo': 'string 1', 'bar': 'string 1', 'ham': 1, 'spam': 1}
Run Code Online (Sandbox Code Playgroud)

最后一个测试doc3包含共享引用; 既'string 1'1存在只是一次在存储器中,与含有这些对象的多个引用字典中.