как работает itertools.tee, можно ли дублировать тип itertools.tee для сохранения его «статуса»? - PullRequest
6 голосов
/ 18 октября 2010

Ниже приведены некоторые тесты о itertools.tee:

    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]  

Мой вопрос

  1. Как работает тройник и почему иногда у оригинального iter «есть данные», а иногда нет?
  2. Могу ли я сохранить итэр-глубокую копию в качестве "семени статуса", чтобы сохранить исходный статус итератора и использовать его позже?
  3. Могу ли я поменять 2 итера или 2 itertools.tee?

Спасибо!

1 Ответ

11 голосов
/ 18 октября 2010

tee берет на себя оригинальный итератор; как только вы наберете итератор, откажитесь от исходного итератора, поскольку он принадлежит вам (если вы действительно не знаете, что делаете).

Вы можете сделать копию тройника с помощью модуля copy:

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

... или позвонив по номеру a.__copy__().

Остерегайтесь того, что tee работает, отслеживая все повторяющиеся значения, использованные исходным итератором, которые все еще могут использоваться копиями.

Например,

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

В этот момент объект тройника, лежащий в основе b и c, прочитал одно значение, 1. Он хранит это в памяти, так как он должен помнить это, когда c повторяется. Он должен хранить каждое значение в памяти, пока он не будет использован всеми копиями тройника.

Следствием этого является то, что вы должны быть осторожны с «сохранением состояния», копируя тройник. Если вы на самом деле не потребляете никаких значений из тройника «сохраненное состояние», вы заставите тройник хранить каждое значение , возвращенное итератором, в памяти навсегда (до тех пор, пока скопированный тройник не будет сброшен и взысканных).

...