繁体   English   中英

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

[英]How does python iterator for list actually works?

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

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 迭代器如何通过大小如此小并保持列表的“旧”值?

迭代器本身包含对列表的引用。 由于lst是反弹而不是变异,因此该引用不会改变。

>>> lst = [1, 2, 3]
>>> itr = iter(lst)
>>> lst[:] = ['a', 'b', 'c']
>>> for x in itr:
...   print x
... 
a
b
c

迭代器引用列表对象而不是名称。 因此, 名称lst 重新分配给另一个对象不会影响迭代器; 名称绑定到对象,并引用对象,但名称不是对象本身。

您可以使用gc.get_referents迭代器引用的对象的窥探:

>>> 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]

正如您将注意到的,迭代器仍然引用第一个列表对象。


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

执行模型 - 命名和绑定

欢迎使用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变量名只是标记,指的是空间中的某个对象。 当你在名为lstlist上调用iter时,迭代器对象类获取指向实际对象的指针,甚至现在它的名称都不是lst

如果您可以修改原始对象,通过调用appendextendpopremove等,迭代器行为将受到影响。 但是当你分配一个新的值lst ,创建一个新的对象(如果它以前不存在),以及lst只是开始指向这个新的对象。

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

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

额外:

# The friend goes and buys more clothes.
lst1.extend([6, 7, 8])

# You call the mugger and ask him to take a shot at the friend again.
itr.next()    # But the mugger says, chill man he's got nothing now
              # raises StopIteration

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM