Python 委托(delegate)模式——如何避免循环引用?

标签 python delegates circular-reference

我想问一下,在 Python 中使用委托(delegate)模式是否会导致循环引用,如果是,实现它以确保对象及其委托(delegate)将被垃圾回收的最佳方式是什么?

在 Objective C 中,通过使用对委托(delegate)的弱引用可以避免上述问题。在 C++ 中,我们不对委托(delegate)调用 delete。我在这里找到了 Python 的弱引用模块的链接:http://docs.python.org/library/weakref.html .似乎一个合理的方法可能是创建一个弱引用来引用使用此模块的实例变量,但我不确定。

因为我在 google 上搜索了这个问题却找不到答案,我想知道这是否是 Python 中的一个问题,或者是否有一个通用的解决方案(不需要 weakref 模块)我我不知道吗?此外,我在提问之前确实搜索了 stackoverflow,但我发现的问题一般涉及循环导入或委托(delegate)模式,而不是特定于 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 implementation detail: CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references. See the documentation of the gc module for information on controlling the collection of cyclic garbage. Other implementations act differently and CPython may change. Do not depend on immediate finalization of objects when they become unreachable (ex: always close files).

原文可在此处找到:http://docs.python.org/reference/datamodel.html大胆的设置是我的。

以下帖子更清楚地解释了循环引用对象的问题以及为什么它会阻止对这些对象进行垃圾回收(至少在典型设置中):http://www.electricmonk.nl/log/2008/07/07/python-destructor-and-garbage-collection-notes/ .

此外,我刚刚看到 Alex Martellli 对以下关于 Python 用户是否应该担心循环引用的问题的回复:Should I worry about circular references in Python?从他的回答中,我了解到即使循环引用的对象最终会被垃圾收集,但也会有开销。它是否重要取决于程序。

此外,他提到使用 Python 的 weakref 模块,但没有明确说明如何使用。

因此,我想添加以下问题来澄清一些 Unresolved 问题:

  1. 文档说垃圾收集不能保证循环 引用的对象。但是从回复看来不是 案件。所以我误解了这段话还是进一步 我错过了哪些细节?
  2. 我想使用弱引用,如 Alex 的回复和我的 问题,是否可以完全避免开销问题?

再次感谢您的回复。

最佳答案

Python 已经进行了垃圾收集。如果您用 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.delegate = y 而不是调用 x.setDelegate(y)。您可以在 Python 中重载成员访问,因此编写方法没有任何好处。

关于Python 委托(delegate)模式——如何避免循环引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10613102/

相关文章:

python - Bigquery - 通过 python 将新数据行插入到表中

Javascript 内存泄漏 : why would assigning object to null work?

.net - 在 .NET 框架中遇到自递归程序集引用

Python(Flask) 变硬排序服装排序

python - 如何使用 Python 防止进出慢速 Cassandra 节点的流量

python - 本地机器 _tkinter.TclError : couldn't connect to display ":0"

c# - 委托(delegate)、 Action 、事件、Lambda 表达式和 MVVM

swift - 在单独的类 Swift 中委托(delegate)

c# - 这是什么代码 : Func < T, string > 我不明白

c# - 解决循环引用 (C#)