python - Python: can view objects show keys of zombie dictionaries?
问题描述
Here is my example code:
#!/usr/bin/env python3
myDict = {'a':1, 'b':2, 'c':3}
myKeys = myDict.keys()
# myDict = {} # toggle this line
myDict['y'] = 4
for myKey in myDict:
print('D ' + myKey)
for myKey in myKeys:
print('K ' + myKey)
If you run the program as shown here (with the line in the middle commented out), you get this output, which is exactly what I expected. The lines with the prefix D
(loop over dictionary) have the same values as the lines with the prefix K
(loop over keys of dictionary):
D a
D b
D c
D y
K a
K b
K c
K y
Now remove the hash and activate the line that was commented out. When you run the modified program, you get this:
D y
K a
K b
K c
But I expected one of these behaviors:
- either:
After
myDict = {}
was executed,myKeys
has become empty too (since it is a view object that always views the keys of its parent dictionary). Adding the item with the key'y'
should result in this output:
D y
K y
- or:
After
myDict = {}
was executed, a new version of myDict was created and the previous version of myDict was destroyed, somyKeys
has no longer any parent dictionary and therefor is pointing to null. So in this case looping over myKeys should throw an error.
But to me is looks as if the old version of myDict has become some kind of zombie, and myKeys is displaying the keys of this zombie.
So, here are my questions:
- Is it true, that in my program myKeys shows keys of a zombie dictionary if the line in the middle is activated?
- Is it reliable behavior, that myKeys will always show the keys of the previous version of the dictionary? (That would be very helpful for a program that I'm writing just now.)
- Is there a way to revive the zombie dictionary? (I have all keys. Can I get the values too?)
解决方案
The fundamental issue in your understanding here is that:
myDict = {}
Does nothing to the original dict
, assignment never mutates, so the object that myDict
was referring to is unmodified. Python objects will stay alive as long as something refers to them. CPython uses reference counting, and as an implementation detail, will reclaim objects immediately when their reference count reaches zero.
However, the dict_keys
view object you created internally references the dictionary it is acting as a view over, so the original dictionary still has at least one reference to it, since the view object is alive. Note, though, the dict_keys
API does not expose this reference, so if it is the only reference, you cannot really access your dict anymore (in any sane way).
Is it reliable behavior, that myKeys will always show the keys of the previous version of the dictionary?
You are misunderstanding the behavior. It is showing the keys of the same dictionary it has always been showing. There is no previous dictionary. The view is over the object, it doesn't care or know which variables happen to be referring to that object at any given time.
It's the same reason that if you do:
x = 'foo'
container = []
container.append(x)
x = 'bar'
print(container[0])
will still print "foo". Objects have no idea what names are referencing them at any given time, and should not care. And when one reference changes, the other references don't magically get updated.
推荐阅读
- vbscript - VBScript 查询命名空间值,如果 % 则运行 X.bat
- http - Firefox 返回没有 http 状态码的页面
- mysql - 如何在phpmyadmin中使用带有X分钟的触发器插入行后删除同一tabke中的行?
- episerver - Episerver – 为什么要绕过属性设置器?
- html - 无法在我的网页中放置背景图片
- r-markdown - Rmarkdown:是否可以仅在标签集中显示当前标签的目录
- android - 防止改造查询参数被转义
- php - 如何在 Web 应用程序中存储选项列表
- magento2 - 在可配置中显示缺货色板(Magento 2.2.6)
- c# - lamda中的linq如何将其转换为正确的方式