2010-10-18 13 views
5

A continuación se presentan algunas pruebas sobre itertools.tee:cómo funciona itertools.tee, puede escribir "itertools.tee" para guardar su "estado"?

li = [x for x in range(10)] 
    ite = iter(li) 
================================================== 
    it = itertools.tee(ite, 5) 
    >>> type(ite) 
    <type 'listiterator'> 
    >>> type(it) 
    <type 'tuple'> 
    >>> type(it[0]) 
    <type 'itertools.tee'> 
    >>> 

    >>> list(ite) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(it[0])   # here I got nothing after 'list(ite)', why? 
    [] 
    >>> list(it[1]) 
    [] 
====================play again=================== 
    >>> ite = iter(li) 
    it = itertools.tee(ite, 5) 
    >>> list(it[1]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(it[2]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(it[3]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(it[4]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(ite) 
    []      # why I got nothing? and why below line still have the data? 
    >>> list(it[0]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(it[0]) 
    [] 
====================play again===================  
    >>> ite = iter(li) 
    itt = itertools.tee(it[0], 5) # tee the iter's tee[0]. 
    >>> list(itt[0]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(itt[1]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(it[0]) 
    []        # why this has no data? 
    >>> list(it[1]) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    >>> list(ite) 
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

Mi pregunta es

  1. ¿Cómo y por qué camiseta trabajo a veces el original iter 'tiene datos' y otra vez que no lo hace?
  2. ¿Puedo guardar una copia profunda iter como una "semilla de estado" para mantener el estado del iterador sin formato y ponerlo en un sitio para usarlo más tarde?
  3. ¿Puedo cambiar 2 iters o 2 itertools.tee?

¡Gracias!

+0

No estoy seguro de si entiendo su pregunta, pero creo que no debe tocar el iterador original después de usar 'itertools.tee' para multiplicarlo. Deberías usar los iteradores get 'n + 1' de' tee' y usar uno de esos como 'original' para 'rastrear el estado' lo que quieras decir con ese – Kimvais

Respuesta

11

tee toma el iterador original; una vez que sacas un iterador, descarta el iterador original ya que el tee lo posee (a menos que realmente sepas lo que estás haciendo).

Se puede hacer una copia de una camiseta con el módulo copy:

import copy, itertools 
it = [1,2,3,4] 
a, b = itertools.tee(it) 
c = copy.copy(a) 

... o llamando a.__copy__().

Tenga en cuenta que tee funciona haciendo un seguimiento de todos los valores iterados que se han consumido desde el iterador original, que aún pueden ser consumidos por las copias.

Por ejemplo,

a = [1,2,3,4] 
b, c = itertools.tee(a) 
next(b) 

En este punto, el tee subyacente b y c objeto ha leído un valor, 1. Está almacenando eso en la memoria, ya que tiene que recordarlo cuando se itera c. Tiene que mantener cada valor en la memoria hasta que sea consumido por todas las copias del tee.

La consecuencia de esto es que debe tener cuidado con "guardar el estado" copiando un tee. Si realmente no consume ningún valor del tee "estado guardado", hará que el tee guarde cada valor devuelto por el iterador en la memoria para siempre (hasta que el tee copiado se descarte y se recoja).

+0

gracias #Glenn, por lo que se puede pensar que un buffer de datos podría conducta como iter, ¿verdad? por lo que puede no ser adecuado para grandes conjuntos de datos, y ¿hay alguna forma de duplicar el iter "puro" para una sola secuencia? Sé que la copia profunda no puede funcionar en un iter. – user478514

+1

No, no hay forma en general de copiar un iterador. Los iteradores * pueden * exponer '__copy__' como lo hacen las instancias' tee', pero normalmente no lo hacen. –

Cuestiones relacionadas