Đây là một ví dụ có liên quan từ các tài liệu mô-đun itertools :
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
Đối với Python 2, bạn cần itertools.izip
thay vì zip
:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
Cách thức hoạt động:
Đầu tiên, hai trình lặp song song a
và b
được tạo ( tee()
cuộc gọi), cả hai đều trỏ đến phần tử đầu tiên của lần lặp ban đầu. Vòng lặp thứ hai, b
được di chuyển 1 bước về phía trước (lệnh next(b, None)
)). Tại thời điểm này chỉ a
đến s0 và b
trỏ đến s1. Cả hai a
và b
có thể đi qua bộ lặp ban đầu một cách độc lập - hàm izip lấy hai bộ lặp và tạo các cặp phần tử được trả về, tiến lên cả hai bộ lặp với cùng tốc độ.
Một cảnh báo: tee()
hàm tạo ra hai vòng lặp có thể tiến độc lập với nhau, nhưng nó có chi phí. Nếu một trong các trình vòng lặp tiến xa hơn các trình lặp khác, thì tee()
cần phải giữ các phần tử đã tiêu thụ trong bộ nhớ cho đến khi trình vòng lặp thứ hai quay lại chúng (nó không thể 'tua lại' trình vòng lặp gốc). Ở đây không có vấn đề gì vì một trình vòng lặp chỉ đi trước một bước so với trình lặp khác, nhưng nói chung, thật dễ dàng để sử dụng nhiều bộ nhớ theo cách này.
Và vì tee()
có thể lấy một n
tham số, nên nó cũng có thể được sử dụng cho nhiều hơn hai trình lặp song song:
def threes(iterator):
"s -> (s0,s1,s2), (s1,s2,s3), (s2, s3,4), ..."
a, b, c = itertools.tee(iterator, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)