1

我需要创建一个可以访问其子级但也可以访问其父级的容器。这是一个简单的例子,说明我是如何考虑这样做的:

import numpy as np
import gc


class Node(object):

    def __init__(self, name):
        self.parent = None
        self.child = []
        self.name = name
        self.mem_tracer = np.ones(10 ** 6)

    def append(self, obj):
        assert(isinstance(obj, Node))
        self.child.append(obj)
        obj.parent = self

但是,当我尝试删除节点时出现内存问题(请注意,属性 mem_tracer 只是为了能够查看对象是否已从内存中删除)

此代码显示了问题(给出了每一行的内存状态):

print 'start'                    # 16.96Mb

a = Node('0')                    # 24.79Mb

a.append(Node('0/0'))            # 32.61Mb
a.append(Node('0/1'))            # 40.42Mb

a.child[0].append(Node('0/0/0')) # 48.24Mb
a.child[0].append(Node('0/0/1')) # 56.06Mb

a.child[1].append(Node('0/1/0')) # 63.87Mb
a.child[1].append(Node('0/1/1')) # 71.69Mb

del a.child[0]                   # 71.69Mb

gc.collect()                     # 48.24Mb

垃圾收集器无法收集已删除对象,因为对它的引用仍然存在于其子代中(尽管它们不再在任何地方引用)。我们可以在最后一行看到,显式调用gc.collect解决了问题,但我更愿意摆脱它,因为它非常耗时!

那么除了将其存储到属性中之外,还有其他方法可以访问父容器吗?提前致谢。

4

1 回答 1

0

你有两个选择:

  • 手动删除obj.parent
  • 用于weakref保持对父级的伪引用。

有关更多信息,请参阅文档weakref

于 2016-03-29T14:06:09.043 回答