Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于列表的python迭代器实际上是如何工作的?_Python_List_Iterator - Fatal编程技术网

用于列表的python迭代器实际上是如何工作的?

用于列表的python迭代器实际上是如何工作的?,python,list,iterator,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。迭代器的大小如何能如此之小并保

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

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
重新分配给另一个对象无论如何都不会影响迭代器;名称绑定到对象,并引用对象,但名称不是对象本身

您可以窥探迭代器引用的对象:

您会注意到,迭代器仍然引用第一个列表对象


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


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

假设你有一个朋友,你雇了一个抢劫犯来抢劫他。现在你告诉抢劫犯你的朋友是电话簿上的第三个插孔(
globals

NTL;DR:Python变量名只是标记,它引用了空间中的某个对象。 当您在名为
lst
列表上调用
iter
时,迭代器对象类会获取指向实际对象的指针,甚至现在它的名称也不是
lst

如果可以通过调用
append
extend
pop
remove
等修改原始对象,迭代器的行为将受到影响。但是,当您为
lst
指定一个新值时,将创建一个新对象(如果它以前不存在的话),并且
lst
只是开始指向该新对象

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

额外:

# 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

这与对象引用无关,迭代器只是在内部存储它已对完整列表进行了迭代。

您没有更改列表,而是创建了一个完全不相关的新列表。
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
# 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