2010-09-29 13 views
5

Dla małego projektu, nad którym pracuję, muszę przejrzeć listę. Dla każdego elementu tego cyklu muszę rozpocząć kolejny cykl na tej samej liście, przy czym pierwszy element jest pierwszym elementem nowego cyklu. Na przykład chciałbym być w stanie wyprodukować coś takiego:Pythonowy sposób kopiowania obiektu iterowalnego

1, 2, 3, 4, 1, 2, 3, 4, 1, ... 
2, 3, 4, 1, 2, 3, 4, 1, 2, ... 
3, 4, 1, 2, 3, 4, 1, 2, 3, ... 
4, 1, 2, 3, 4, 1, 2, 3, 4, ... 
1, 2, 3, 4, 1, 2, 3, 4, 1, ... 
... 

myślałem, że kopiowanie itertools.cycle po każdym .next() by zachować aktualny stan, tak, że mogę rozpocząć nowy cykl z elementem z cyklu "zewnętrznego". Lub nawet "zresetować wskaźnik cyklu" do starszej pozycji. Próbowałem następujące:

>>> import itertools, copy 
>>> a = itertools.cycle([1, 2, 3, 4]) 
>>> b = copy.copy(a) 

ale mam ten błąd:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.6/copy.py", line 95, in copy 
    return _reconstruct(x, rv, 0) 
    File "/usr/lib/python2.6/copy.py", line 323, in _reconstruct 
    y = callable(*args) 
    File "/usr/lib/python2.6/copy_reg.py", line 93, in __newobj__ 
    return cls.__new__(cls, *args) 
TypeError: cycle expected 1 arguments, got 0 

Wiem, że istnieje wiele różnych sposobów, aby osiągnąć to, co chcę, ale szukam jakiegoś krótkiego, jasnego i pythonic kodu. Może ktoś ma inny pomysł, a nawet fragment? Fakt, że to not possible to copy iterator objects obudził moje zainteresowanie. Czy istnieje najlepsza praktyka w sytuacjach, gdy ktoś chce mieć kopię wersji iteracyjnej? Czy też jest to niemądrze i bezużyteczne kopiowanie iterables?

+1

Nie są głupie [PEP 323] (http://www.python.org/dev/peps/pep-0323/) uważane co copyable iteratorami. – Matt

Odpowiedz

5

Is there a best-practice in situations where one wants a copy of an iterable?

itertools.tee daje dwa iteratory że każdy poddają te same elementy jak oryginał, ale ma oryginalny i zapamiętuje wszystko to plony, więc nie można używać już oryginału. Nie pomogłoby to jednak, ponieważ zapamiętywałoby te cykliczne wartości, dopóki nie pojawi się błąd MemoryError.

Or is copying iterables silly and useless in general?

Iteratory są zdefiniowane tak, aby miały aktualny stan i dawały element. Nie możesz powiedzieć, czy przyniosą one te same przedmioty w przyszłości, czy też które przedmioty wydały w przeszłości. Prawdziwy egzemplarz musiałby zrobić jedno i drugie, więc jest to niemożliwe!

W twoim przypadku tak trywialnie jest zrobić nowy cykl, który wolałbym zrobić, niż spróbować skopiować istniejący. Np

def new_cycle(seq, last=None): 
    if last is None: 
     return cycle(seq) 
    else: 
     it = cycle(seq) 
     while next(it) != last: 
      pass 
     return it 
Powiązane problemy