当最后一个引用不存在时,为什么未从WeakValueDictionary中删除值

我有以下Python程序:

import weakref

class NumberWord:
  def __init__(self,word):
    self.word = word
  def __repr__(self):
    return self.word

dict = weakref.WeakValueDictionary()

print(f"[A] {len(dict)}")
print(f"dict.get(0) = {dict.get(0)}")
print(f"dict.get(1) = {dict.get(1)}")

list = []
list.append(NumberWord("zero"))
dict[0] = list[0]

print(f"[B] {len(dict)}")
print(f"dict.get(0) = {dict.get(0)}")
print(f"dict.get(1) = {dict.get(1)}")

list.append(NumberWord("one"))
dict[1] = list[1]
print(list)

print(f"[C] {len(dict)}")
print(f"dict.get(0) = {dict.get(0)}")
print(f"dict.get(1) = {dict.get(1)}")

list.pop()
print(list)

print(f"[D] {len(dict)}")
print(f"dict.get(0) = {dict.get(0)}")
print(f"dict.get(1) = {dict.get(1)}")

list.pop()
print(list)

print(f"[E] {len(dict)}")
print(f"dict.get(0) = {dict.get(0)}")
print(f"dict.get(1) = {dict.get(1)}")

我期望以下行为:

  • 在步骤[A]中,字典为空

  • 在步骤[B]中,字典包含dict[0] = NumberWord("zero")

  • 在步骤[C]中,字典包含dict[0] = NumberWord("zero")dict[1] = NumberWord("one")

  • 在步骤[D]中,字典包含dict[1] = NumberWord("one")(由于列表中唯一的强引用已消失,因此删除了“零”)

  • 在步骤[E]中,字典再次为空(由于列表中唯一的强引用消失了,因此删除了“一个”)

一切正常, 步骤[E]:“一个”不会不会消失。为什么不呢?

这是实际输出:

>>> import weakref
>>> 
>>> class NumberWord:
...   def __init__(self,word):
...     self.word = word
...   def __repr__(self):
...     return self.word
... 
>>> dict = weakref.WeakValueDictionary()
>>> 
>>> print(f"[A] {len(dict)}")
[A] 0
>>> print(f"dict.get(0) = {dict.get(0)}")
dict.get(0) = None
>>> print(f"dict.get(1) = {dict.get(1)}")
dict.get(1) = None
>>> 
>>> list = []
>>> list.append(NumberWord("zero"))
>>> dict[0] = list[0]
>>> 
>>> print(f"[B] {len(dict)}")
[B] 1
>>> print(f"dict.get(0) = {dict.get(0)}")
dict.get(0) = zero
>>> print(f"dict.get(1) = {dict.get(1)}")
dict.get(1) = None
>>> 
>>> list.append(NumberWord("one"))
>>> dict[1] = list[1]
>>> print(list)
[zero,one]
>>> 
>>> print(f"[C] {len(dict)}")
[C] 2
>>> print(f"dict.get(0) = {dict.get(0)}")
dict.get(0) = zero
>>> print(f"dict.get(1) = {dict.get(1)}")
dict.get(1) = one
>>> 
>>> list.pop()
one
>>> print(list)
[zero]
>>> 
>>> print(f"[D] {len(dict)}")
[D] 2
>>> print(f"dict.get(0) = {dict.get(0)}")
dict.get(0) = zero
>>> print(f"dict.get(1) = {dict.get(1)}")
dict.get(1) = one
>>> 
>>> list.pop()
zero
>>> print(list)
[]
>>> 
>>> print(f"[E] {len(dict)}")
[E] 1
>>> print(f"dict.get(0) = {dict.get(0)}")
dict.get(0) = zero
>>> print(f"dict.get(1) = {dict.get(1)}")
dict.get(1) = None
>>> 
>>> 
chensong651 回答:当最后一个引用不存在时,为什么未从WeakValueDictionary中删除值

我刚刚发现了答案。

原因是特殊变量_仍包含上一次评估的结果。

上次评估为list.pop(),其结果为NumberWord("zero")

只要此结果仍存储在_中,我们将继续拥有强引用,而弱引用也不会消失。

我们可以通过进行另一次评估来确认这一理论。此时,_将包含一个不同的值,弱引用将消失:

如果我们在以上示例的末尾执行以下附加语句:

_
5 + 5
_
print(f"[F] {len(dict)}")
print(f"dict.get(0) = {dict.get(0)}")
print(f"dict.get(1) = {dict.get(1)}")

然后我们得到以下输出:

>>> _
zero
>>> 5 + 5
10
>>> _
10
>>> print(f"[F] {len(dict)}")
[F] 0
>>> print(f"dict.get(0) = {dict.get(0)}")
dict.get(0) = None
>>> print(f"dict.get(1) = {dict.get(1)}")
dict.get(1) = None
本文链接:https://www.f2er.com/2780728.html

大家都在问