簡體   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