其他分享
首页 > 其他分享> > 循环引用不调用弱引用回调

循环引用不调用弱引用回调

作者:互联网

我正在尝试为具有循环引用的Python类编写终结器.我发现弱引用回调是way to go.不幸的是,似乎从未调用过用作回调的lambda.例如,运行以下代码:

def del_A(name):
    print('An A deleted:' + name)

class A(object):
    def __init__(self, name):
        print('A created')
        self.name = name
        self._wr = weakref.ref(self, lambda wr, n = self.name: del_A(n))

class B(object):
    def __init__(self):
        print('B created')

if __name__ == '__main__':
    a = A('a1')
    b = B()
    a.other = b
    b.other = a

返回:

A created
B created

删除循环引用将使lambda回调起作用(打印“ An A Deleted:a1”).也可以通过简单的函数调用替换lambda,但是在初始化弱引用时(而不是在调用回调时)参数值是固定的:

self._wr = weakref.ref(self, del_A(self.name))
...
a = A('a1')
a.name = 'a2'
b = B()
a.other = b
b.other = a

返回:

A created
An A deleted:a1
B created

知道为什么lambda回调不适用于循环引用吗?

解决方法:

使用时

 self._wr = weakref.ref(self, lambda wr, n = self.name: del_A(n))  

仅在self将要完成时才调用回调.

回调未得到调用的原因是

a = A('a1')
b = B()
a.other = b   # This gives a another attribute; it does not switch `a` away from the original `a`
b.other = a

不会导致定案.原始的a仍然存在.

如果将代码更改为,则将调用回调

a = A('a1')
b = B()
a = b
b = a

使用时

self._wr = weakref.ref(self, del_A(self.name))

那么您的回调为无. del_A(self.name)不是对函数的引用,它是函数本身.因此,del_A(self.name)立即打印出一个A Deleted:a1(在a1最终确定之前),并返回值None,这成为weakref的默认回调.

标签:weak-references,python,lambda
来源: https://codeday.me/bug/20191106/2001241.html