【发布时间】:2023-02-23 02:58:51
【问题描述】:
我正在使用 set 来保存对可调用对象的弱引用。这些可以是函数、可调用实例(即使用 __call__ 方法)和绑定方法。在 docs 之后,我将 weakref.WeakMethod 用于绑定方法,将 weakref.ref 用于其他可调用对象。
我面临的问题最好用一个例子来解释:
from weakref import ref, WeakMethod
class Callbacks:
def method(self, *args, **kwargs):
print('method()')
def __call__(self, *args, **kwargs):
print('__call__()')
cb = Callbacks()
listeners = set()
listeners.add(ref(cb))
print(f'#listeners: expected = 1, actual = {len(listeners)}')
listeners.add(WeakMethod(cb.method))
print(f'#listeners: expected = 2, actual = {len(listeners)}')
这打印:
#listeners:预期= 1,实际= 1
#listeners:预期= 2,实际= 1深入挖掘,我确实看到了
WeakMethod(cb.method) == ref(cb),尽管cb.method != cb。我错过了什么?
【问题讨论】:
-
无法复制;当我执行
python3 -munittest tmp.py时,所有4个测试都通过了(以上是tmp.py的内容)。 -
鉴于被测代码根本不使用弱引用,除了
weakref模块本身之外,您是否正在测试任何有用的东西并不清楚。 -
@chepner 改写了问题和动机(希望如此)清楚。
-
好的,是的,这更清楚了,是的,这对我来说确实很奇怪。该文档仅提到
WeakMethod模拟对绑定方法的引用,所以也许它真的只是对对象的弱引用,稍后“重建”对绑定方法的弱引用。 (注意cb.method创建了一个新的每次使用method实例;它不仅仅是像cb那样引用长寿命对象的表达式。)