为什么当最后一个强引用消失时,没有从 WeakValueDictionary 中删除值
Why is value not removed from WeakValueDictionary when last stong reference goes away
我有以下 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")
("zero" 被删除,因为列表中唯一的强引用消失了)
在步骤 [E] 中,dict 再次为空("one" 被删除,因为列表中唯一的强引用消失了)
一切正常 除了 步骤 [E]:"one" 不会 消失。为什么不呢?
这里是实际输出:
>>> 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
>>>
>>>
我自己找到了答案。
原因是特殊变量_
仍然包含上次计算的结果。
上次评价为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
我有以下 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")
("zero" 被删除,因为列表中唯一的强引用消失了)在步骤 [E] 中,dict 再次为空("one" 被删除,因为列表中唯一的强引用消失了)
一切正常 除了 步骤 [E]:"one" 不会 消失。为什么不呢?
这里是实际输出:
>>> 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
>>>
>>>
我自己找到了答案。
原因是特殊变量_
仍然包含上次计算的结果。
上次评价为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