2017-04-18 53 views
0

我只是偶然發現或多或少(回答this問題),人們可以至少一些迭代器使用copy.copy()複製(不發球)迭代器:這是一個功能或「實施細節」

Q複製:由於這在module documentation中根本沒有提及,所以我想知道這是官方功能還是可能在不通知的情況下從語言中刪除的內容。

補充問:請問itertools.tee存在的相同注意事項適用於此處嗎?即可能會消耗大量內存,可能會更有效地創建列表。

這是爲什麼這在我看來,一個非常有用的功能的例子(嘗試做同樣與tee):

def triu_indices(n): 
    """indices into the upper triangle of a square matrix""" 
    yi = iter(range(n)) 
    for y in yi: 
     for x in copy.copy(yi): 
      yield y, x 

for y, x in triu_indices(4): 
    print(y, x) 

# 0 1 
# 0 2 
# 0 3 
# 1 2 
# 1 3 
# 2 3 

更新:我不好,我應該已經明確表示,這也適用於「適當的」迭代器(我測試了itertools.productitertools.combinations)不僅適用於「不是真的迭代器」range。它也適用於list迭代器。它確實不是使用文件(_io.TextIOWrapper)對象。

回答

1

如果沒有記錄,可能確實不能依賴它。也就是說,這種類型的功能似乎更容易記錄下來,後來被刪除。然而,你的例子只是複製一個特定類型的迭代器,即範圍迭代器,並且你通常不應該期望能夠複製任意迭代器。

使用您使用的範圍迭代器,至少在當前實現中,沒有像tee那樣的開銷類型。看起來copy正在使用pickle __reduce_ex__機制,這意味着複製範圍迭代器本質上會創建一個新的範圍迭代器對象,該對象應該與原始對象一樣具有迭代效率。它不存儲單個值。 (我可以瞬間完成copy.copy(iter(range(10**1000))),並且沒有任何顯着的內存使用情況。)

每個迭代器類型都不同,並且可能會或可能不會定義複製自身的方式。看起來你可以複製範圍迭代器,但這並不意味着你可以假設你能夠複製你遇到的任何迭代器。事實上,一般情況下,假設你不能這樣做會更安全,因爲迭代器協議相當普遍,許多迭代器不會公開復制它們所需的內部狀態。

+0

@mgilson,BrenBarn,謝謝你的回答。他們似乎相容,這總是讓人放心。只是爲了讓我看清楚這一點;你是否說它基本上歸結爲可揀性?那些需要緩衝的迭代器通常不被支持?如果你沒有注意到我已經用迭代器更新了這個問題(以及我已經檢查過的迭代器)。 –

+0

@PaulPanzer:我在我的回答中添加了一些註釋。基本上,能夠複製一個迭代器與複製其他任何東西沒有什麼不同:如果它定義了複製自己的方法,則可以複製它,否則不能。看起來你發現了一些可以被複制的迭代器,但是並沒有真正說出是否可以複製一般的迭代器。此外,迭代器通常依賴於「私有」內部狀態,因此遇到的隨機迭代器可能比您遇到的其他隨機對象更難以複製。 – BrenBarn