2010-10-18 14 views
5

Im Folgenden sind einige Tests über itertools.tee:wie itertools.tee funktioniert, kann type 'itertools.tee' dupliziert werden, um seinen "Status" zu speichern?

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] 

Meine Frage

ist
  1. Wie funktioniert Tee und warum manchmal die ursprüngliche iter ‚hat Daten‘ und andere Zeit nicht?
  2. Kann ich eine tiefere iter-Kopie als "Status-Seed" behalten, um den Status des rohen Iterators beizubehalten und ihn später zu verwenden?
  3. Kann ich 2 Iter oder 2 itertools.tee tauschen?

Vielen Dank!

+0

Ich bin mir nicht sicher, ob ich Ihre Frage verstehe, aber ich __think__ Sie sollten den ursprünglichen Iterator nicht berühren, nachdem Sie 'itertools.tee' verwendet haben, um ihn zu multiplizieren. Sie sollten get 'n + 1'-Iteratoren von' tee' verwenden und eines davon als das 'Original' verwenden, um 'den Status' zu verfolgen, was immer Sie damit meinen, – Kimvais

Antwort

11

tee übernimmt den ursprünglichen Iterator; Sobald Sie einen Iterator abtun, verwerfen Sie den ursprünglichen Iterator, da das T-Stück ihn besitzt (es sei denn, Sie wissen wirklich, was Sie tun).

Sie können eine Kopie eines T-Stücks machen mit dem copy Modul:

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

... oder durch a.__copy__() Aufruf.

Beachten Sie, dass tee funktioniert, indem Sie alle iterierten Werte verfolgen, die vom ursprünglichen Iterator konsumiert wurden und die möglicherweise noch von den Kopien konsumiert werden.

Zum Beispiel

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

An diesem Punkt werden die Objekt-T zugrunde liegenden b und c hat einen Wert lesen, 1. Es speichert das im Speicher, da es sich daran erinnern muss, wenn c iteriert wird. Es muss jeden Wert im Speicher behalten, bis er von allen Kopien des Tees verbraucht wird.

Die Konsequenz daraus ist, dass Sie vorsichtig sein müssen, wenn Sie den Status speichern, indem Sie ein T-Stück kopieren. Wenn Sie tatsächlich keine Werte vom "gespeicherten Status" -T-Stück konsumieren, veranlassen Sie das T-Stück, jeden Wert, der vom Iterator für immer im Speicher zurückgegeben wird, zu behalten (bis das kopierte T-Stück verworfen und gesammelt wird).

+0

Dank #Glenn, so kann Tee als Datenpuffer gedacht werden Verhalten als iterer, richtig? es ist also möglicherweise nicht für große Datenmengen geeignet, und gibt es eine Möglichkeit, die "reine" iter für eine einzelne Sequenz zu duplizieren? Ich weiß, tiefe Kopie kann nicht auf einem Iter arbeiten. – user478514

+1

Nein, es gibt keine Möglichkeit, einen Iterator zu kopieren. Iteratoren * können '__copy__' als 'tee'-Instanzen angeben, tun dies aber normalerweise nicht. –