列表的python迭代器如何实际工作?

时间:2016-10-22 14:53:07

标签: python list iterator

假设我们有以下列表,我们正在为它创建一个迭代器:

lst = [1,2,3]
itr = iter(lst)

接下来假设我们正在使用完全不同的值更改列表:

lst = ['a', 'b', 'c']

如果我运行以下循环:

for x in itr:
   print x

我们将获得'1,2,3'。但为什么?据我所知,迭代器不会复制迭代对象的所有值。至少三个元素列表的迭代器与100000个元素的列表具有相同的大小。 sys.getsizeof(i)返回64。如何使迭代器的大小如此之小并保持列表的“旧”值?

3 个答案:

答案 0 :(得分:4)

迭代器本身包含对列表的引用。由于ssh-rsa <key> <email>是反弹而不是变异,因此该引用不会改变。

lst

答案 1 :(得分:3)

迭代器引用列表对象而不是名称。所以将名称>>> import gc >>> lst = [1,2,3] >>> itr = iter(lst) # return an iterator for the list >>> lst = ['a', 'b', 'c'] # Bind name lst to another object >>> gc.get_referents(itr)[0] [1, 2, 3] 重新分配给另一个对象不会影响迭代器;名称绑定到对象,并引用对象,但名称不是对象本身。

您可以使用Counter获取迭代器引用的对象的窥探:

read_csv

正如您所注意到的,迭代器仍然是指第一个列表对象。

以下参考资料将帮助您了解有关Python中名称和绑定的更多信息:

gc.get_referents

答案 2 :(得分:2)

欢迎使用Python的对象参考系统。变量名与存储在内存中的实际对象并没有很深的关系。

假设您有一个朋友lst,并且您雇用抢劫 iter来抢劫他。现在你告诉抢劫犯你的朋友是电话簿中的第三个杰克(globals)。

lst = [1, 2, 3]
itr = iter(lst)     # iter object now points to the list pointed to by lst
                    # it doesn't care about its name (doesn't even knows its name actually)

# Now the mugger has found the friend, and knows his address (the actual object in memory).
# The mugger catches him, and takes his jacket.
print itr.next()    # outputs 1

# Now the telephone directory was updated (yes it's updated very frequently).
lst1 = lst             # your friend is now the fourth Jack
lst = ['a', 'b', 'c']  # someone else is the third Jack now
                       # but mugger doesn't know, he won't see the directory again

print itr.next()       # (output 2), mugger takes t-shirt, and leaves him for now

# Meanwhile your friend buys new clothes.
lst1.append(4)      # here the actual object pointed to by iter is updated
lst1.append(5)

# You call the mugger and say, don't leave him until he's got nothing.
# The mugger goes full retard.
for i in iter:
    print i         # outputs 3, 4 and 5

NTL; DR :Python变量名只是标记,指的是空间中的某个对象。 当您在名为iter的{​​{1}}上调用list时,迭代器对象类获取指向实际对象的指针,即使现在它的名称也是{{1} }。

如果您可以通过调用lstlstappendextend等来修改原始对象,则会影响迭代器行为。但是,当您为pop分配新值时,会创建一个新对象(如果它之前不存在),并且remove只是开始指向该新对象。

如果没有其他对象指向它,垃圾收集器将删除原始对象(在这种情况下lst指向它,因此原始对象不会被删除)。

http://foobarnbaz.com/2012/07/08/understanding-python-variables/

额外:

lst

这与对象引用没有任何关系,迭代器只在内部存储它迭代完整列表。