2012-06-12 24 views
5

Cả hai đối tượng danh sách và đối tượng islice đều có thể lặp lại nhưng tại sao lại có sự khác biệt này trong kết quả.từ thư viện itertools

r = [1, 2, 3, 4]    
i1, i2 = tee(r) 
print [e for e in r if e < 3] 
print [e for e in i2] 
#[1, 2] 
#[1, 2, 3, 4] 


r = islice(count(), 1, 5)   
i1, i2 = tee(r) 
print [e for e in r if e < 3] 
print [e for e in i2] 
#[1, 2] 
#[] 

Trả lời

14

Vấn đề ở đây là tee() nhu cầu tiêu thụ các giá trị từ các iterator ban đầu, nếu bạn bắt đầu tiêu thụ chúng từ iterator gốc, nó sẽ không thể hoạt động tốt. Trong ví dụ danh sách của bạn, quá trình lặp lại chỉ đơn giản là bắt đầu lại. Trong ví dụ máy phát điện, nó đã cạn kiệt và không còn giá trị nào được tạo ra nữa.

Đây cũng là tài liệu:

Khi tee() đã làm cho một sự chia rẽ, bản gốc iterable không nên được sử dụng bất cứ nơi nào khác; nếu không, các iterable có thể được nâng cao mà không có các đối tượng tee được thông báo.

Source

Chỉnh sửa để minh họa cho điểm trong sự khác biệt giữa một danh sách và một máy phát điện:

>>> from itertools import islice, count 
>>> a = list(range(5)) 
>>> b = islice(count(), 0, 5) 
>>> a 
[0, 1, 2, 3, 4] 
>>> b 
<itertools.islice object at 0x7fabc95d0fc8> 
>>> for item in a: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in a: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in b: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in b: 
...  print(item) 
... 
>>> 
+0

nhưng đối tượng danh sách và đối tượng islice cần phải hoạt động tương tự, phải không? – John

+1

@John Không, khi bạn lặp lại danh sách, bạn sẽ có một trình lặp mới mỗi lần, nghĩa là bạn vẫn nhận được các giá trị. Khi bạn sử dụng 'islice()' bạn sẽ nhận được một trình tạo, nó sẽ tạo ra các giá trị một lần, và sau đó bị cạn kiệt. Hãy tự mình thử - chỉ cần lặp lại một danh sách hai lần, sau đó lấy một vòng tròn và lặp lại hai lần đó - lưu ý sự khác biệt về hành vi. –

+0

@John Để làm cho hai ví dụ hoạt động tương tự, sử dụng 'r = iter ([1,2,3,4])' thay vì 'r = [1,2,3,4]'. – clacke

0

Trong comprehensions danh sách của bạn, bạn muốn thay thế r với i1.