2016-05-26 30 views
2

我想做一個itertools.cycle對象的淺拷貝,但我不知道如何,因爲它沒有內置的拷貝方法。我想要實現類似以下內容的創建循環的副本,重複執行幾次,然後再次複製原始代碼,並從循環開始開始迭代幾次複製itertools循環對象

c = "ABCD" 
cyc = itertools.cycle(c) 

cyc_copy = cyc.copy() 
for i in range(2): 
    print(next(cyc_copy)) 
cyc_copy = cyc.copy() 
for i in range(2): 
    print(next(cyc_copy)) 

> A 
    B 
    A 
    B 
+4

['itertools.tee'](https://docs.python.org/3/library/itertools.html#itertools.tee)。 – vaultah

+0

'itertools.tee'起作用,但它需要存儲原始'循環'迭代器的所有輸出,包括循環返回時的重複輸出。 – user2357112

+3

您是否處於只能訪問循環而不是原始迭代的情況?似乎只是製造新的週期將是明智的。 –

回答

2
如果你需要經過週期的循環很多,這可能是昂貴的

它可能需要一些重構,但工廠在這裏工作會很好。

from itertools import cycle 

cycle_factory = lambda: cycle('1234') 

c1 = cycle_factory() 
print next(c1) # 1 

c2 = cycle_factory() 
print next(c2) # 1 

否則,我不確定您是否能夠滿足每次循環開始時的條件。基於班級的方式也可以工作,但需要更多的開銷。

itertools.tee方法的問題之一是,它將恢復迭代,tee-d迭代器停止而不是從頭開始。因此,你必須在開始時開球。如果您無法控制週期的產生,這可能是唯一的選擇。

0

copy應該做的伎倆:

>>> from copy import copy 
>>> cyc_copy = copy(cyc) 
>>> next(cyc_copy) 
'A' 
>>> next(cyc_copy) 
'B' 
>>> cyc_copy = copy(cyc) 
>>> next(cyc_copy) 
'A' 
>>> next(cyc_copy) 
'B' 
+1

[這似乎失敗了一些週期。](http://ideone.com/bKWVDc) – user2357112

+1

嘗試調用複製週期給我'TypeError:週期預期1個參數,得到0'。它依賴於版本嗎?我正在使用python 2.7.6 –

+0

進一步測試時,它似乎是版本依賴。 Python 2給出了'TypeError'。 Python 3給出了[不同的,微妙的錯誤](http://ideone.com/lw5Ynd) - 循環不是獨立的。他們分享一些潛在的狀態,導致下一個影響另一個狀態。 – user2357112

1

複製本身會遇到問題的惡性循環。例如,copy.copying it doesn't produce independent copies

,而不是試圖複製週期,我建議您從原始對象重新創建它:

new_cyc = itertools.cycle(c) 

如果從做你原來的週期的對象是一個迭代器,你不能只是調用cycle就可以了反覆。相反,做一個清單,你打電話之前cycle第一次,並保持列表:

c_list = list(c) 
cyc = itertools.cycle(c_list) 

# later 
new_cyc = itertools.cycle(c_list) 

如果從做你原來的週期的對象是一個迭代器,可能會或可能不會是無限的,你不能安全請撥打list。相反,你可以在之前之前創建週期和copy.copy當你需要做一個新的週期時,先進的發球臺。 (tee支持複製。)

c_tee, c_tee2 = itertools.tee(c) 
cyc = itertools.cycle(c_tee2) 

# Copy c_tee, not the c_tee2 we already used. 
new_cyc = itertools.cycle(copy.copy(c_tee)) 

這一切假設你控制循環的創建。如果您從其他地方接收到循環,則可能無法訪問循環的對象。在這種情況下,你最好的選擇是tee這個循環本身。

cyc_master, cyc1 = itertools.tee(cyc) 
# Use cyc1 

# Later 
cyc2 = copy.copy(cyc_master) 
1

您可以創建一個自定義的類做你想要什麼:

import itertools 

class CopyCycle: 
    def __init__(self, iterable): 
     self.iterable = iterable 
     self._cycle = itertools.cycle(self.iterable) 

    def cycle(self): 
     return self 

    def __iter__(self): 
     return self 

    def next(self): 
     return self._cycle.next() 

    def __next__(self): #Python 3+ 
     return self._cycle.next() 

    def copy(self): 
     return CopyCycle(self.iterable) 


if __name__ == '__main__': 
    cyc = CopyCycle("ABCD").cycle() 
    for i in range(5): 
     print(next(cyc)) 

    cyc_copy = cyc.copy() 
    for i in range(2): 
     print(next(cyc_copy)) 
    cyc_copy = cyc.copy() 
    for i in range(2): 
     print(next(cyc_copy)) 

輸出:

 
A 
B 
C 
D 
A 
A 
B 
A 
B 
0

方法1:做兩個itertools.cycle對象

import itertools 
c = 'ABCD' 
cyc1 = itertools.cycle(c) 
cyc2 = itertools.cycle(c) 
for _ in range(2): print(next(cyc1)) # prints A\nB\n 
for _ in range(2): print(next(cyc2)) # prints A\nB\n 

<script src="//repl.it/embed/IRcx/0.js"></script>

[優選的解決方案]方法2:分成N個迭代器通過使用itertools.tee

import itertools 
cyc = itertools.cycle('ABCD') 
cyc1, cyc2 = itertools.tee(cyc, 2) 
for _ in range(2): print(next(cyc1)) # prints A\nB\n 
for _ in range(2): print(next(cyc2)) # prints A\nB\n 

<script src="//repl.it/embed/IRcx/2.js"></script>

警告使用copy.copy功能將無法正常創建迭代器的副本使用copy模塊

import itertools, copy 
cyc = itertools.cycle('ABCD') 
cyc1 = copy.copy(cyc) 
cyc2 = copy.copy(cyc) 
for _ in range(2): print(next(cyc1)) # prints A\nB\n 
for _ in range(2): print(next(cyc2)) # prints C\nD\n 

<script src="//repl.it/embed/IRcx/3.js"></script>

使用copy模塊解決方法:此可能的解決方案可以是使用copy.deepcopy功能。

import itertools, copy 
cyc = itertools.cycle('ABCD') 
cyc1 = copy.deepcopy(cyc) 
cyc2 = copy.deepcopy(cyc) 
for _ in range(2): print(next(cyc1)) # prints A\nB\n 
for _ in range(2): print(next(cyc2)) # prints A\nB\n 

<script src="//repl.it/embed/IRcx/4.js"></script>