[英]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變量名只是標記,指的是空間中的某個對象。 當你在名為lst
的list
上調用iter
時,迭代器對象類獲取指向實際對象的指針,甚至現在它的名稱都不是lst
。
如果您可以修改原始對象,通過調用append
, extend
, pop
, remove
等,迭代器行為將受到影響。 但是當你分配一個新的值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.