2011-02-14 29 views
65

Khi nào tốt hơn nên sử dụng zip thay vì itertools.izip?Khi nào nên sử dụng zip thay vì izip?

+0

Một lý do ủng hộ của 'zip', quá rõ ràng nhưng vẫn giá trị chỉ ra, đó là 'izip' trả về một' iterator' mà có thể chỉ được duyệt qua một lần. tức là trong 'ii = izip (a, b); f (ii); g (ii) ', ở đây một danh sách rỗng' [] 'được chuyển tới' g'. – Causality

Trả lời

33

Khi bạn biết bạn sẽ muốn danh sách đầy đủ các mục được tạo (ví dụ: để chuyển đến một hàm có thể sửa đổi danh sách đó tại chỗ). Hoặc khi bạn muốn ép buộc các đối số, bạn sẽ chuyển đến zip() để được đánh giá hoàn toàn tại điểm cụ thể đó.

+1

Sẽ không tốt hơn nếu sử dụng izip trong trường hợp đầu tiên vì nó nhanh hơn vì nó sử dụng lại tuple và không có lý do thực sự nào để không sử dụng izip? – user1815201

+1

@ user1815201: 'izip' chỉ tái sử dụng' tuple' nếu 'tuple' được phát hành trước khi bắt đầu lặp lại tiếp theo, vì vậy nó không giúp bạn đạt được gì. Điều đó nói rằng, bất kỳ mất mát là tầm thường quá, vì vậy tôi đồng ý rằng có rất ít lý do không sử dụng 'izip' độc quyền, gói với' danh sách' nếu bạn cần một 'danh sách'; bạn thực sự có thể thực hiện điều này theo cách "thích hợp" bằng cách thêm 'từ mã zip trong tương lai_builtins vào mã Py2, làm cho' zip' đơn giản thành 'izip' (chuẩn bị cho chuyển đổi Py3). – ShadowRanger

4

Trong 2.x, khi bạn cần danh sách thay vì một trình lặp.

+0

Bạn có thể cho tôi một ví dụ mà điều đó có thể xảy ra không? –

+3

Không thực sự. Đó là lý do tại sao tôi có xu hướng thích 'itertools.izip()' ngoại trừ những lợi ích sẽ hoàn toàn thống kê. –

+2

Một trường hợp, khi bạn cần danh sách, là khi bạn định truy cập các mục của kết quả theo chỉ mục hoặc cần tìm tổng chiều dài. 'lst = zip (lst_a, lst_b)' cho phép 'lst [1]' hoặc 'len (lst)'. Tuy nhiên, đối với 'ilst = itertools.izip (lst_a, lst_n)' bạn sẽ thất bại khi cố gắng 'ilst [1]' hoặc 'len (ilst)'. –

79

zip tính tất cả danh sách cùng một lúc, izip chỉ tính toán các phần tử khi được yêu cầu.

Một sự khác biệt quan trọng là 'zip' trả về một danh sách thực tế, 'izip' trả về một 'đối tượng izip', mà không phải là một danh sách và không hỗ trợ tính năng danh sách cụ thể (chẳng hạn như lập chỉ mục):

>>> l1 = [1, 2, 3, 4, 5, 6] 
>>> l2 = [2, 3, 4, 5, 6, 7] 
>>> z = zip(l1, l2) 
>>> iz = izip(l1, l2) 
>>> isinstance(zip(l1, l2), list) 
True 
>>> isinstance(izip(l1, l2), list) 
False 
>>> z[::2] #Get odd places 
[(1, 2), (3, 4), (5, 6)] 
>>> iz[::2] #Same with izip 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'itertools.izip' object is unsubscriptable 

Vì vậy, nếu bạn cần một danh sách (một đối tượng không giống như danh sách), chỉ cần sử dụng 'zip'.

Ngoài việc này, 'izip' có thể hữu ích để tiết kiệm bộ nhớ hoặc chu kỳ.

Ví dụ: mã sau đây có thể thoát khỏi sau vài chu kỳ, do đó không cần phải tính toán tất cả các mục trong danh sách kết hợp:

lst_a = ... #list with very large number of items 
lst_b = ... #list with very large number of items 
#At each cycle, the next couple is provided 
for a, b in izip(lst_a, lst_b): 
    if a == b: 
     break 
print a 

sử dụng zip sẽ tính tất cả(a, b) cặp vợ chồng trước khi bước vào chu kỳ.

Hơn nữa, nếu lst_alst_b rất lớn (ví dụ hàng triệu bản ghi), zip(a, b) sẽ xây dựng một danh sách thứ ba với không gian gấp đôi.

Nhưng nếu bạn có danh sách nhỏ, có thể zip sẽ nhanh hơn.

+4

Cảm ơn. Tuy nhiên, điều này chủ yếu là câu trả lời khi 'izip' tốt hơn' zip' ... –

+6

Bạn nói đúng. Tôi bắt đầu với ý định tốt và sau đó rơi vào công cụ lý thuyết ... – Don

3

Thư viện itertools cung cấp "trình lặp" cho các hàm Python phổ biến. Từ tài liệu itertools, "Giống như zip() ngoại trừ nó trả về một trình lặp thay vì danh sách." I trong izip() có nghĩa là "trình lặp".

Trình lặp của Python là trình tự "nạp chậm" giúp tiết kiệm bộ nhớ trên danh sách trong bộ nhớ thông thường. Vì vậy, bạn sẽ sử dụng itertools.izip (a, b) khi hai đầu vào a, b là quá lớn để giữ trong bộ nhớ cùng một lúc.

Tra cứu các khái niệm liên quan đến Python hiệu quả tuần tự chế biến:

"generators" & "yield" 
"iterators" 
"lazy loading" 
+0

Được giải thích rõ ràng. –

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