Python的代理模式 - 如何避免循环引用?(Python Delegate Pattern -

2019-09-17 06:13发布

我会问,如果使用Python中的代理模式会导致循环引用如果是这样,这将是最好的方式来实施,以确保对象及其委托将被垃圾收集?

在Objective C,上述问题是通过使用弱引用到委托避免。 在C ++中,我们不叫删除该委托。 我发现一个链接到Python的弱引用模块的位置: http://docs.python.org/library/weakref.html 。 这似乎是一个可行的办法可能是创建一个弱引用来引用使用这个模块的实例变量,但我不知道。

正如我GOOGLE了这个问题,并没有能够找到答案,我不知道这是否是连问题Python或是否有一个共同的解决方案(无需为weakref模块),我不知道的? 另外,我做搜索计算器问过,但问题我发现无论是对付进口的圆形或一般委托模式,而不是具体到Python和循环引用的问题。

感谢您事先的任何答复。

下面列出的是一些代码的玩具例子来帮助说明我的问题。 我以这种方式实现的代码和它的作品,但我不知道是否存储在末尾垃圾收集。

class A(object):
    def __init__(self):
        self.delegate = None

        # Some other instance variables that keep track of state for performing some tasks.

    def doSomething(self):
        if self.delegate is not None:
            self.delegate.doSomething()
        else:
            print('Cannot perform task because delegate is not set.')

    # Other methods not shown.

class B(object):
    def __init__(self):
        self.a = A() # Need to keep object 'a' from garbage collected so as to preserve its state information.
        self.a.delegate = self  # Is this a circular reference? How to 'fix' it so that A and B will eventually be garbage collected?

    def doSomething(self):
        print('B doing something')

    # Other methods not shown.

编辑

阅读一些的答复后,我决定澄清我的问题。 据我所知,Python有垃圾收集。 我不知道是它是否会在循环引用的对象进行垃圾回收。 我的担忧从Python的文档下面这段话梗:

CPython的实现细节:CPython的目前使用与(可选)延迟环状连接的垃圾,其中,一旦收集大多数对象,因为它们变得不可达的检测的引用计数方案,但不能保证,收集含有循环引用垃圾 。 查看控制循环垃圾收集GC模块的信息的文档。 其他实现的行为不同和CPython中可能会改变。 不依赖于对象的直接定稿时,他们变得不可(例如:始终关闭文件)。

在其原始形式的通道可以在这里找到: http://docs.python.org/reference/datamodel.html大胆的设定是我的。

以下职位提供循环引用对象的问题更清楚的解释,为什么它会阻止对这些对象的垃圾收集(至少在一个典型的设置): http://www.electricmonk.nl/log/2008/07/07 /蟒蛇,析构函数和无用信息收集笔记/ 。

此外,我只是遇到了亚历克斯Martellli的答复对Python用户是否应该担心循环引用以下问题: 我应该担心Python中的循环引用? 从他的回答,我推测,即使循环引用的对象将最终被垃圾收集但仍然会有开销。 无论是显著取决于程序。

此外,他还提到要使用Python的weakref模块,但并没有明确说怎么样。

因此,我想补充以下问题,澄清一些悬而未决的问题:

  1. 该文件说garbaged回收不保证为循环引用的对象。 但是,从答复似乎并非如此。 所以,我有误解的推移,还是有进一步的细节,我已经错过了吗?
  2. 我想用一个弱引用,如Alex的答复,我的问题指出,将避免的开销问题是完全?

再次感谢您的答复。

Answer 1:

蟒蛇已经进行垃圾回收。 你只需要做一些特别的东西,如果你用C编写你自己的容器类型,作为扩展。

演示:运行此程序,看内存的使用不会爬。

class C(object):
    pass

def circular():
    for x in range(10**4):
        for y in range(10**4):
            a = C()
            b = C()
            a.x = b
            b.x = a

circular()

附注:下面的函数并不做任何事情,将其删除。

def setDelegate(self, delegate):
    self.delegate = delegate

而不是调用的x.setDelegate(y)可以使用x.delegate = y 。 可以重载在Python成员访问,所以有编写的方法没有任何好处。



Answer 2:

为什么不是被垃圾收集在结束了吗? 当脚本结束,蟒蛇执行完成后,内存的整个部分将被标记为垃圾收集和(最终)操作系统恢复。

如果你在一个长期运行的程序运行此,一旦A和B都间接引用,那么内存将被回收。



文章来源: Python Delegate Pattern - How to avoid circular reference?