2010-10-18 29 views
5

Dưới đây là một số xét nghiệm về itertools.tee:cách thức hoạt động của itertools.tee, có thể nhập 'itertools.tee' được sao chép để lưu "trạng thái" của nó?

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] 

Câu hỏi của tôi là

  1. Làm thế nào để làm việc tee và tại sao đôi khi bản gốc iter 'có dữ liệu' và khác thời gian nó không?
  2. Tôi có thể giữ bản sao sâu lặp lại là "hạt giống trạng thái" để giữ trạng thái của trình lặp thô và sử dụng nó sau này không?
  3. Tôi có thể trao đổi 2 iters hoặc 2 itertools.tee?

Cảm ơn!

+0

Tôi không chắc chắn nếu tôi hiểu câu hỏi của bạn, nhưng tôi __think__ bạn không nên chạm vào trình lặp ban đầu sau khi bạn sử dụng 'itertools.tee' để nhân nó. Bạn nên sử dụng các biến lặp 'n + 1' từ' tee' và sử dụng một trong số đó là 'nguyên bản' để' theo dõi trạng thái 'bất kỳ ý nghĩa nào của bạn bằng cách – Kimvais

Trả lời

11

tee tiếp nhận trình lặp ban đầu; một khi bạn tee một iterator, loại bỏ các iterator ban đầu kể từ khi tee sở hữu nó (trừ khi bạn thực sự biết những gì bạn đang làm).

Bạn có thể tạo một bản sao của một tee với các module copy:

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

... hoặc bằng cách gọi a.__copy__().

Hãy coi chừng rằng tee hoạt động bằng cách theo dõi tất cả các giá trị được lặp lại đã được sử dụng từ trình lặp ban đầu, mà vẫn có thể được tiêu thụ bởi các bản sao.

Ví dụ,

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

Tại thời điểm này, đối tượng tee cơ bản bc đã đọc một giá trị, 1. Nó lưu trữ trong bộ nhớ, vì nó phải nhớ nó khi c được lặp lại. Nó phải giữ mọi giá trị trong bộ nhớ cho đến khi nó được tiêu thụ bởi tất cả các bản sao của tee.

Hậu quả của việc này là bạn cần phải cẩn thận với "trạng thái lưu" bằng cách sao chép một tee. Nếu bạn không thực sự tiêu thụ bất kỳ giá trị nào từ tee "trạng thái đã lưu", bạn sẽ khiến tee giữ mọi giá trị trả về bởi trình lặp trong bộ nhớ mãi mãi (cho đến khi tee được sao chép bị hủy và thu thập).

+0

cảm ơn #Glenn, vì vậy tee có thể được coi là bộ đệm dữ liệu tiến hành như lặp lại, phải không? do đó, nó có thể không thích hợp cho tập dữ liệu lớn, và có cách nào có thể lặp lại "thuần túy" lặp cho một chuỗi duy nhất? Tôi biết bản sao sâu không thể làm việc trên một lần lặp. – user478514

+1

Không, không có cách nào nói chung để sao chép một trình lặp. Iterators * có thể * phơi bày '__copy__' như các trường hợp' tee', nhưng thường thì không. –

Các vấn đề liên quan