Python 为什么将这些对象(来自生成器)添加到列表时会发生更改?
所以我试图从生成器中获取对象,并将它们添加到列表中。但当我将它们添加到列表中时,列表中会填充空对象,而不是我添加的对象。为什么呢 此代码Python 为什么将这些对象(来自生成器)添加到列表时会发生更改?,python,Python,所以我试图从生成器中获取对象,并将它们添加到列表中。但当我将它们添加到列表中时,列表中会填充空对象,而不是我添加的对象。为什么呢 此代码 #!/usr/bin/python # Create a graph with 5 nodes from snap import * G = TUNGraph.New() for i in range(5): G.AddNode(i) # Ids of these nodes are 0, 1, 2, 3, 4 for node in G.No
#!/usr/bin/python
# Create a graph with 5 nodes
from snap import *
G = TUNGraph.New()
for i in range(5):
G.AddNode(i)
# Ids of these nodes are 0, 1, 2, 3, 4
for node in G.Nodes(): # G.Nodes() is a generator
print node.GetId()
lst = []
for node in G.Nodes():
lst.append(node)
print
# All of the nodes magically change to have ID -1
print [node.GetId() for node in lst]
print
# The nodes in the original graph are unchanged
for i in G.Nodes():
print i.GetId()
产生输出
0
1
2
3
4
[-1, -1, -1, -1, -1]
0
1
2
3
4
好的!在对原件的评论中,我们确定
for node in G.Nodes(): # G.Nodes() is a generator
print node.GetId()
print id(node) # NEW LINE HERE
每次为id(节点)
打印相同的内容
这意味着生成器每次都返回相同的对象,并在调用之间对其进行变异。列表中的“对象”都是相同的对象,其状态反映了节点()
实现在封面下所做的任何内部操作
我认为这是一个糟糕的设计,虽然我没有使用SNAP,所以不能确定。这是一个我经常看到的微效率技巧。当CPython在内部执行类似操作时,它首先检查生成的对象上的引用计数是否为1。当且仅当它为1时,CPython知道它只持有对生成对象的引用,因此对其进行变异是安全的。但是,如果refcount大于1,CPython将创建一个新的要屈服的对象(因为用户可能会保留最后一个屈服的对象,就像@eeee在他的示例代码中所做的那样)
我会向软件包作者抱怨这种行为。它充其量也很容易混淆和出错:-(尝试在第二个循环中添加
打印id(节点)
。我怀疑(但不知道)节点()iterator每次都返回相同的对象。如果打印的所有ID都是相同的,那么肯定是相同的。是的。这会解释很多。我想知道为什么会这样。谢谢您的帮助!