24

Django 文档在这个问题上这样说:

另请注意,Django 默认将信号处理程序存储为弱引用,因此如果您的处理程序是本地函数,它可能会被垃圾回收。为防止这种情况,请在调用信号的 connect() 时传递 weak=False。

我无法找到任何理由说明为什么这是默认设置,而且我不明白为什么你会想要一个你明确注册的信号隐式消失。那么这里弱引用的用例是什么?为什么它是默认值?

我意识到在 99% 的情况下这两种方式都可能无关紧要,但显然这里有些东西我不明白,我想知道是否有任何潜伏的“陷阱”可能有一天会咬我。

4

2 回答 2

14

信号处理程序存储为弱引用,以避免它们引用的对象不被垃圾收集(例如在显式删除信号处理程序之后),只是因为信号仍在飞来飞去。

于 2009-07-10T17:26:14.897 回答
6

绑定方法保留对它们所属对象的引用(否则,它们无法填充self,参见Python 文档)。考虑以下代码:

import gc
class SomeLargeObject(object):
    def on_foo(self): pass

slo = SomeLargeObject()
callbacks = [slo.on_foo]

print [o for o in gc.get_objects() if isinstance(o, SomeLargeObject)]
del slo
print [o for o in gc.get_objects() if isinstance(o, SomeLargeObject)]
callbacks = []
print [o for o in gc.get_objects() if isinstance(o, SomeLargeObject)]

输出:

[<__main__.SomeLargeObject object at 0x15001d0>]
[<__main__.SomeLargeObject object at 0x15001d0>]
[]

在回调中保留弱引用时要知道的一件重要事情是,您不能直接绑定弱引用方法,因为它们总是动态创建的:

>>> class SomeLargeObject(object):
...  def on_foo(self): pass
>>> import weakref
>>> def report(o):
...  print "about to collect"
>>> slo = SomeLargeObject()
>>> #second argument: function that is called when weakref'ed object is finalized
>>> weakref.proxy(slo.on_foo, report)
about to collect
<weakproxy at 0x7f9abd3be208 to NoneType at 0x72ecc0>
于 2009-07-10T18:46:07.793 回答