由于循环引用而未调用弱引用回调
我正在尝试为具有循环引用的 Python 类编写一个终结器。我发现弱引用回调是 方式去。不幸的是,我用作回调的 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
returns:
A created
B created
删除循环引用会使 lambda 回调起作用(打印“An A returned: 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
returns:
A created
An A deleted:a1
B created
知道为什么 lambda 回调不适用于循环引用吗?
I'm trying to write a finalizer for Python classes that have circular references. I found out that weak reference callbacks are the way to go. Unfortunately, it seems the lambda I use as a callback is never called. For example, running this code:
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
returns:
A created
B created
Removing the circular reference makes the lambda callback works ('An A deleted: a1' is printed). Replacing the lambda by a simple function call works too, but the parameter value is fixed when initializing the weak reference, and not when calling the callback:
self._wr = weakref.ref(self, del_A(self.name))
...
a = A('a1')
a.name = 'a2'
b = B()
a.other = b
b.other = a
returns:
A created
An A deleted:a1
B created
Any idea why the lambda callback does not work with circular references?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您使用
回调时,只会在
self
即将完成时调用。回调未被调用的原因是
不会导致
a
被最终确定。原来的a
仍然存在。如果您将代码更改为“
当您使用时
,那么您的回调为
None
”, 则会调用该回调。del_A(self.name)
不是对函数的引用,它是函数调用本身。因此,del_A(self.name)
立即打印An A returned:a1
(在a1
真正最终确定之前),并返回值>None
,成为弱引用的默认回调。When you use
the callback will only be called when
self
is about to be finalized.The reason why the callback is not getting called is because
does not cause
a
to be finalized. The originala
still exists.The callback would be called if you changed the code to
When you use
then your callback is
None
.del_A(self.name)
is not a reference to a function, it is a function call itself. Sodel_A(self.name)
printsAn A deleted:a1
immediately (beforea1
is really finalized), and returns with the valueNone
, which becomes the default callback for the weakref.我想我终于找到了在存在弱引用的情况下不调用回调的原因:
如果 "weakref 对象在它之前死亡
看起来
,当删除循环引用时,类 A 的弱引用属性在回调有机会被调用之前就被删除了。一种解决方案是附加终结器(即弱引用及其回调)到终结器列表。例如:
将打印:
注意 do_work() 是必要的,否则终结器会在回调有机会被调用之前被删除,显然,必须正确管理终结器以避免构建巨大的列表。弱引用,但这是另一个问题。
I think I finally found the reason why the callback is not called in the presence of a weak reference:
Weak reference callbacks are not called if the "weakref object dies before the object it
references"
It seems that when circular references are deleted, the weak reference attribute of class A is deleted before the callback has a chance to be called. One solution, is to append the finalizer (i.e., the weak reference and its callback) to a list of finalizers. For example:
will print:
Note that do_work() is necessary, otherwise finalizers gets deleted before the callbacks have a chance to be called. Obviously, finalizers has to be managed properly to avoid building a huge list of weak references, but this is another issue.
循环引用会自动清除。有一些例外,例如定义
__del__
方法的类。通常你不需要定义
__del__
方法Circular references are cleaned up automatically. There are a few exceptions, such as classes that define a
__del__
method.Usually you do not need to define a
__del__
method