所以我试图从生成器中获取对象并将它们添加到列表中。但是当我将它们添加到列表中时,列表会填充空对象而不是我添加的对象。那是为什么?
此代码
#!/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
答案 0 :(得分:3)
OK!在对原文的评论中,我们建立了
for node in G.Nodes(): # G.Nodes() is a generator
print node.GetId()
print id(node) # NEW LINE HERE
每次为id(node)
打印相同的内容。
这意味着生成器每次都返回相同的对象,并在调用之间进行变异。列表中的“对象”都是相同的对象,其状态反映了Nodes()
实现在内的所有内部工作。
我认为这是糟糕的设计,虽然我没有使用过SNAP,所以无法确定。这是我经常看到的微效率技巧。当CPython在内部执行类似这样的操作时,它首先检查所产生的对象上的引用计数是否为1.当且仅当它为1时,CPython知道它包含 only 对所产生的引用的引用对象,所以改变它是安全的。但是如果refcount大于1,CPython会创建一个新的对象来生成(因为用户可能会保留最后一个产生的对象 - 正如@eeeeeeeeee在他的示例代码中所做的那样)。
我向包裹作者抱怨这种行为。这最多令人困惑且容易出错: - (