2010-09-29 21 views
5

Para un pequeño proyecto en el que estoy trabajando necesito pasar por una lista. Para cada elemento de este ciclo tengo que comenzar otro ciclo a través de la misma lista, con el primer elemento como primer elemento del nuevo ciclo. Por ejemplo, me gustaría ser capaz de producir algo como esto:Manera pitónica de copiar un objeto iterable

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

pensé que la copia de un itertools.cycle después de cada .Next() sería conservar el estado actual, de modo que pueda comenzar el nuevo ciclo con el elemento del ciclo "exterior". O incluso "restablecer el puntero del ciclo" a una posición anterior. He intentado lo siguiente:

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

pero tengo este error:

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 

Sé que hay muchas maneras diferentes para lograr lo que quiero, pero estoy buscando un poco de código corto, claro y Pythonic. Tal vez alguien tiene otra idea o incluso un fragmento? El hecho de que es not possible to copy iterator objects despertó mi interés. ¿Hay una mejor práctica en situaciones donde uno quiere una copia de un iterable? ¿O está copiando iterables tontos e inútiles en general?

+1

No son tonto, [PEP 323] (http://www.python.org/dev/peps/pep-0323/) considerado hacer iteradores copiable. – Matt

Respuesta

5

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

itertools.tee le da dos iteradores que cada una rinda los mismos elementos que el original, pero se necesita el original y memoriza todo lo que se produce, por lo que no puede utilizar el original más. Sin embargo, no ayudaría aquí, porque seguiría memorizando estos valores ciclados hasta que obtenga un MemoryError.

Or is copying iterables silly and useless in general?

iteradores son simplemente definidos para tener un estado actual y ceder un elemento. No puede decir si cederán los mismos artículos en el futuro o qué artículos arrojaron en el pasado. Una copia real tendría que hacer ambas cosas, ¡así que es imposible!

En su caso, es tan trivial hacer un nuevo ciclo que preferiría hacer que intentar copiar uno existente. Por ejemplo:

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