如何在Python中创建一个“死亡”的弱引用?

5

有没有比这种做法更好的方法:

def create_expired_weakref():
    class Tmp: pass
    ref = weakref.ref(Tmp())
    assert ref() is None
    return ref

背景:我希望在我的弱引用(weakref)中设置默认状态,以便我的类可以执行以下操作:

def __init__(self):
    self._ref = create_expired_weakref()

def get_thing(self):
    r = self._ref()  # I need an empty weakref for this to work the first time
    if r is None:
        r = SomethingExpensive()
        self._ref = weakref.ref(r)
    return r

4
必须使用weakref.ref对象吗?如果您不关心类型,可以将lambda: None用作默认值。 - Aran-Fey
1
@Aran-Fey:好主意——这对我的用例有效,但我仍然很好奇是否有一种方法可以生成真正的弱引用(例如,这将使mypy感到满意)。 - Eric
3
如果你不喜欢 lambda,可以使用 type(None) - wim
2个回答

2
另一种方法是使用鸭子类型。如果您关心的只是它在调用self._ref()时的行为类似于一个已经失效的弱引用,那么您可以这样做: "最初的回答"
self._ref = lambda : None

当我有类似的愿望,希望有一个属性可以返回缓存值(如果有),否则返回None时,我最终使用了以下内容。我使用这个lambda函数进行初始化,然后定义属性:

"最初的回答"

@property
def ref(self):
    return self._ref()

更新:感谢@Aran-Fey提供的建议,我看到他在评论中提出了这个想法,而不是作为答案。最初的回答。

0
使用weakref.finalize可以大有作为:
import weakref

def create_expired_weakref(type_=type("", (object,), {'__slots__':
                                      ('__weakref__',)})):
    obj = type_()
    ref = weakref.ref(obj)
    collected = False

    def on_collect():
        nonlocal collected
        collected = True
    final = weakref.finalize(obj, on_collect)
    del obj

    while not collected:
        pass
    return ref

如果您正在调试,这可能会阻塞线程一段时间,甚至在某些不明显的情况下可能会死锁,但它保证返回一个已过期的弱引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接