2010-09-29 17 views
5

Per un piccolo progetto su cui sto lavorando Devo scorrere un elenco. Per ogni elemento di questo ciclo devo iniziare un altro ciclo attraverso lo stesso elenco, con l'elemento precedente come primo elemento del nuovo ciclo. Per esempio mi piacerebbe essere in grado di produrre qualcosa di simile:Modo Pythonico di copiare un oggetto iterabile

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, ... 
... 

ho pensato che la copia di un itertools.cycle dopo ogni .Next() sarebbe conservare lo stato attuale, in modo che possa iniziare il nuovo ciclo con l'elemento dal ciclo "esterno". O anche "resettare il puntatore del ciclo" su una posizione precedente. Ho provato quanto segue:

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

ma ottenuto questo errore:

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 

So che ci sono molti modi diversi per ottenere ciò che voglio, ma sto cercando un codice breve, chiaro e divinatorio. Forse qualcuno ha un'altra idea o anche un frammento? Il fatto che sia not possible to copy iterator objects ha svegliato il mio interesse. Esiste una best practice in situazioni in cui si desidera una copia di un iterable? O sta copiando iterables sciocco e inutile in generale?

+1

Non sono stupido, [PEP 323] (http://www.python.org/dev/peps/pep-0323/) pensato di fare iteratori copiabili. – Matt

risposta

5

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

itertools.tee ti dà due iteratori che ogni produrrà gli stessi elementi come l'originale, ma ci vuole l'originale e memorizza tutto ciò che produce, quindi non è possibile utilizzare più l'originale. Tuttavia, non sarebbe di aiuto, perché continuerebbe a memorizzare questi valori ciclizzati fino a ottenere un MemoryError.

Or is copying iterables silly and useless in general?

Gli iteratori sono appena definiti per avere uno stato corrente e produrre un articolo. Non puoi dire se arriveranno gli stessi articoli in futuro o quali oggetti hanno ceduto in passato. Una copia reale dovrebbe fare entrambe le cose, quindi è impossibile!

Nel tuo caso è così banale fare un nuovo ciclo che preferirei fare piuttosto che provare a copiare un esistente. Per esempio:

def new_cycle(seq, last=None): 
    if last is None: 
     return cycle(seq) 
    else: 
     it = cycle(seq) 
     while next(it) != last: 
      pass 
     return it 
Problemi correlati