代码之家  ›  专栏  ›  技术社区  ›  Jason C

为什么Django的信号处理默认使用弱引用进行回调?

  •  17
  • Jason C  · 技术社区  · 15 年前

    这个 Django docs 在主题上说:

    还要注意Django存储信号 作为弱引用的处理程序 默认值,因此如果处理程序是本地的 函数,它可能被垃圾收集。 为了防止出现这种情况,当 您调用信号_S connect()。

    我还没有找到任何理由来解释为什么这是默认的,我也不明白为什么你会想要一个你明确注册的信号隐式地消失。那么这里弱引用的用例是什么呢?为什么是违约?

    我意识到这在99%的情况下可能都不重要,但很明显这里有一些我不理解的东西,我想知道是否有什么“gotchas”潜伏着,可能有一天会咬我。

    2 回复  |  直到 15 年前
        1
  •  10
  •   Luper Rouch François Lagunas    15 年前

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

        2
  •  6
  •   Torsten Marek    15 年前

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

    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>]
    []
    

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

    >>> 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>