itertools --- Hàm tạo vòng lặp để lặp hiệu quả¶
Mô-đun này triển khai một số khối xây dựng iterator lấy cảm hứng từ các cấu trúc từ APL, Haskell và SML. Mỗi cái đã được viết lại ở dạng phù hợp với Python.
Mô-đun này tiêu chuẩn hóa một bộ cốt lõi gồm các công cụ nhanh, hiệu quả về bộ nhớ, hữu ích khi sử dụng riêng lẻ hoặc kết hợp với nhau. Cùng nhau, chúng tạo thành một "đại số lặp" giúp xây dựng các công cụ chuyên dụng một cách ngắn gọn và hiệu quả bằng Python thuần túy.
Ví dụ: SML cung cấp công cụ lập bảng: tabulate(f) tạo ra chuỗi f(0), f(1), .... Hiệu ứng tương tự có thể đạt được trong Python bằng cách kết hợp map() và count() để tạo thành map(f, count()).
General iterators:
Trình vòng lặp |
Đối số |
Kết quả |
Ví dụ |
|---|---|---|---|
p [,func] |
p0, p0+p1, p0+p1+p2, ... |
|
|
p, n |
(p0, p1,...,p_n-1),... |
|
|
p, q,... |
p0, p1,... nhựa, q0, q1,... |
|
|
có thể lặp lại |
p0, p1,... nhựa, q0, q1,... |
|
|
dữ liệu, bộ chọn |
(d[0] nếu s[0]), (d[1] nếu s[1]), ... |
|
|
[bắt đầu[, bước]] |
bắt đầu, bắt đầu+bước, bắt đầu+2*bước, ... |
|
|
p |
p0, p1, ... nhựa, p0, p1, ... |
|
|
vị ngữ, seq |
seq[n], seq[n+1], bắt đầu khi vị ngữ thất bại |
|
|
vị ngữ, seq |
các phần tử của seq trong đó vị ngữ(elem) không thành công |
|
|
có thể lặp lại [, khóa] |
các vòng lặp phụ được nhóm theo giá trị của khóa (v) |
|
|
seq, [bắt đầu,] dừng [, bước] |
các phần tử từ seq[start:stop:step] |
|
|
có thể lặp lại |
(p[0], p[1]), (p[1], p[2]) |
|
|
yếu tố [,n] |
elem, elem, elem, ... vô tận hoặc tới n lần |
|
|
chức năng, thứ tự |
func(*seq[0]), func(*seq[1]), ... |
|
|
vị ngữ, seq |
seq[0], seq[1], cho đến khi vị ngữ thất bại |
|
|
nó, n |
it1, it2, ... itn chia một iterator thành n |
|
|
p, q,... |
(p[0], q[0]), (p[1], q[1]), ... |
|
Combinatoric iterators:
Trình vòng lặp |
Đối số |
Kết quả |
|---|---|---|
p, q, ... [lặp lại=1] |
tích Descartes, tương đương với vòng lặp for lồng nhau |
|
p[, r] |
bộ dữ liệu có độ dài r, tất cả các thứ tự có thể, không có phần tử lặp lại |
|
p, r |
các bộ có độ dài r, được sắp xếp theo thứ tự, không có phần tử lặp lại |
|
p, r |
các bộ có độ dài r, được sắp xếp theo thứ tự, với các phần tử lặp lại |
Ví dụ |
Kết quả |
|---|---|
|
|
|
|
|
|
|
|
Chức năng Itertool¶
Các hàm sau đây đều xây dựng và trả về các trình vòng lặp. Một số cung cấp các luồng có độ dài vô hạn, do đó chúng chỉ được truy cập bởi các hàm hoặc vòng lặp cắt bớt luồng.
- itertools.accumulate(iterable[, function, *, initial=None])¶
Tạo một trình vòng lặp trả về tổng tích lũy hoặc kết quả tích lũy từ các hàm nhị phân khác.
Zz000zz mặc định là phép cộng. Zz001zz phải chấp nhận hai đối số, tổng tích lũy và một giá trị từ iterable.
Nếu giá trị initial được cung cấp, quá trình tích lũy sẽ bắt đầu với giá trị đó và đầu ra sẽ có nhiều phần tử hơn phần tử đầu vào có thể lặp lại.
Gần tương đương với:
def tích lũy(iterable, function=operator.add, *,init=None): 'Trả về tổng số đang chạy' # accumulate([1,2,3,4,5]) → 1 3 6 10 15 # accumulate([1,2,3,4,5], ban đầu=100) → 100 101 103 106 110 115 # accumulate([1,2,3,4,5], operator.mul) → 1 2 6 24 120 iterator = iter(có thể lặp lại) tổng = ban đầu nếu ban đầu là Không có: thử: tổng = tiếp theo(iterator) ngoại trừ StopIteration: trở về tổng sản lượng cho phần tử trong iterator: tổng = hàm(tổng, phần tử) tổng sản lượng
Để tính mức chạy tối thiểu, đặt function thành
min(). Để đạt mức tối đa, hãy đặt function thànhmax(). Hoặc đối với sản phẩm đang chạy, đặt function thànhoperator.mul(). Để xây dựng amortization table, hãy tích lũy tiền lãi và áp dụng các khoản thanh toán:>>> dữ liệu = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8] >>> danh sách (tích lũy (dữ liệu, tối đa)) # running tối đa [3, 4, 6, 6, 6, 9, 9, 9, 9, 9] >>> danh sách(tích lũy(dữ liệu, operator.mul)) sản phẩm # running [3, 12, 72, 144, 144, 1296, 0, 0, 0, 0] # Amortize khoản vay 5% trị giá 1000 với 10 khoản thanh toán hàng năm là 90 >>> cập nhật = số dư lambda, thanh toán: vòng(số dư * 1,05) - thanh toán >>> danh sách(tích lũy(lặp lại(90, 10), cập nhật, ban đầu=1_000)) [1000, 960, 918, 874, 828, 779, 728, 674, 618, 559, 497]
Xem
functools.reduce()để biết hàm tương tự chỉ trả về giá trị tích lũy cuối cùng.Added in version 3.2.
Thay đổi trong phiên bản 3.3: Đã thêm tham số function tùy chọn.
Thay đổi trong phiên bản 3.8: Đã thêm tham số initial tùy chọn.
- itertools.batched(iterable, n, *, strict=False)¶
Dữ liệu hàng loạt từ iterable thành các bộ có độ dài n. Lô cuối cùng có thể ngắn hơn n.
Nếu strict là đúng, sẽ tăng
ValueErrornếu đợt cuối cùng ngắn hơn n.Lặp lại đầu vào có thể lặp lại và tích lũy dữ liệu thành các bộ dữ liệu có kích thước tối đa n. Đầu vào được tiêu thụ một cách lười biếng, chỉ đủ để lấp đầy một đợt. Kết quả được trả về ngay khi lô đầy hoặc khi hết lần lặp đầu vào:
>>> Flated_data = ['hoa hồng', 'đỏ', 'tím', 'xanh', 'đường', 'ngọt'] >>> unflattened = list(batched(flattened_data, 2)) >>> không phẳng [('hoa hồng', 'đỏ'), ('hoa tím', 'xanh'), ('đường', 'ngọt')]
Gần tương đương với:
def theo đợt(iterable, n, *, strict=False): # batched('ABCDEFG', 3) → ABC DEF G nếu n < 1: raise ValueError('n phải có ít nhất một') iterator = iter(có thể lặp lại) while batch := tuple(islice(iterator, n)): if nghiêm ngặt và len(batch) != n: tăng ValueError('batched(): batch chưa hoàn thành') sản lượng lô
Added in version 3.12.
Thay đổi trong phiên bản 3.13: Đã thêm tùy chọn strict.
- itertools.chain(*iterables)¶
Tạo một trình lặp trả về các phần tử từ lần lặp đầu tiên cho đến khi hết, sau đó chuyển sang lần lặp tiếp theo, cho đến khi tất cả các lần lặp đều hết. Điều này kết hợp nhiều nguồn dữ liệu vào một trình vòng lặp duy nhất. Gần tương đương với:
chuỗi def(*iterables): # chain('ABC', 'DEF') → A B C D E F cho iterable trong iterables: mang lại lợi nhuận từ iterable
- classmethod chain.from_iterable(iterable)¶
Hàm tạo thay thế cho
chain(). Nhận các đầu vào được xâu chuỗi từ một đối số có thể lặp lại được đánh giá một cách lười biếng. Gần tương đương với:def from_iterable(iterable): # chain.from_iterable(['ABC', 'DEF']) → A B C D E F cho iterable trong iterables: mang lại lợi nhuận từ iterable
- itertools.combinations(iterable, r)¶
Trả về chuỗi con có độ dài r của các phần tử từ iterable đầu vào.
Đầu ra là một dãy con của
product()chỉ giữ lại các mục là dãy con của iterable. Độ dài của đầu ra được cho bởimath.comb(), tính toánn! / r! / (n - r)!khi0 ≤ r ≤ nhoặc 0 khir > n.Các bộ dữ liệu kết hợp được phát ra theo thứ tự từ điển theo thứ tự của iterable đầu vào. Nếu iterable đầu vào được sắp xếp, các bộ dữ liệu đầu ra sẽ được tạo theo thứ tự được sắp xếp.
Các phần tử được coi là duy nhất dựa trên vị trí của chúng chứ không phải giá trị của chúng. Nếu các phần tử đầu vào là duy nhất thì sẽ không có giá trị lặp lại trong mỗi kết hợp.
Gần tương đương với:
kết hợp def (lặp lại, r): # combinations('ABCD', 2) → AB AC AD BC BD CD # combinations(phạm vi (4), 3) → 012 013 023 123 pool = tuple(lặp lại) n = len(pool) nếu r > n: trở về chỉ số = danh sách (phạm vi (r)) mang lại tuple(pool[i] cho i trong chỉ số) trong khi Đúng: vì tôi ở vị trí đảo ngược(range(r)): nếu chỉ số[i] != i + n - r: phá vỡ khác: trở về chỉ số[i] += 1 cho j trong phạm vi (i+1, r): chỉ số[j] = chỉ số[j-1] + 1 mang lại tuple(pool[i] cho i trong chỉ số)
- itertools.combinations_with_replacement(iterable, r)¶
Trả về các chuỗi có độ dài r của các phần tử từ iterable đầu vào cho phép các phần tử riêng lẻ được lặp lại nhiều lần.
Đầu ra là một dãy con của
product(), chỉ giữ các mục là dãy con (với các phần tử có thể lặp lại) của iterable. Số dãy con được trả về là(n + r - 1)! / r! / (n - 1)!khin > 0.Các bộ dữ liệu kết hợp được phát ra theo thứ tự từ điển theo thứ tự của iterable đầu vào. nếu iterable đầu vào được sắp xếp, các bộ dữ liệu đầu ra sẽ được tạo theo thứ tự được sắp xếp.
Các phần tử được coi là duy nhất dựa trên vị trí của chúng chứ không phải giá trị của chúng. Nếu các phần tử đầu vào là duy nhất thì các kết hợp được tạo cũng sẽ là duy nhất.
Gần tương đương với:
def tổ hợp_with_replacement(iterable, r): # combinations_with_replacement('ABC', 2) → AA AB AC BB BC CC pool = tuple(lặp lại) n = len(pool) nếu không phải n và r: trở về chỉ số = [0] * r mang lại tuple(pool[i] cho i trong chỉ số) trong khi Đúng: vì tôi ở vị trí đảo ngược(range(r)): nếu chỉ số[i] != n - 1: phá vỡ khác: trở về chỉ số[i:] = [chỉ số[i] + 1] * (r - i) mang lại tuple(pool[i] cho i trong chỉ số)
Added in version 3.1.
- itertools.compress(data, selectors)¶
Tạo một trình vòng lặp trả về các phần tử từ data trong đó phần tử tương ứng trong selectors là đúng. Dừng khi vòng lặp data hoặc selectors đã hết. Gần tương đương với:
nén def (dữ liệu, bộ chọn): # compress('ABCDEF', [1,0,1,0,1,1]) → A C E F trả về (mốc cho mốc, bộ chọn trong zip (dữ liệu, bộ chọn) nếu bộ chọn)
Added in version 3.1.
- itertools.count(start=0, step=1)¶
Tạo một trình vòng lặp trả về các giá trị cách đều nhau bắt đầu bằng start. Có thể được sử dụng với
map()để tạo các điểm dữ liệu liên tiếp hoặc vớizip()để thêm số thứ tự. Gần tương đương với:số def (bắt đầu = 0, bước = 1): # count(10) → 10 11 12 13 14 ... # count(2,5, 0,5) → 2,5 3,0 3,5 ... n = bắt đầu trong khi Đúng: năng suất n n += bước
Khi đếm bằng số dấu phẩy động, đôi khi có thể đạt được độ chính xác cao hơn bằng cách thay thế mã nhân như:
(start + step * i for i in count()).Thay đổi trong phiên bản 3.1: Đã thêm đối số step và cho phép đối số không nguyên.
- itertools.cycle(iterable)¶
Tạo một trình vòng lặp trả về các phần tử từ iterable và lưu một bản sao của mỗi phần tử. Khi vòng lặp hết, hãy trả về các phần tử từ bản sao đã lưu. Lặp đi lặp lại vô thời hạn. Gần tương đương với:
chu kỳ def (lặp lại): # cycle('ABCD') → A B C D A B C D A B C D ... đã lưu = [] cho phần tử trong iterable: yếu tố năng suất đã lưu.append(phần tử) trong khi lưu: cho phần tử đã lưu: yếu tố năng suất
Itertool này có thể yêu cầu bộ nhớ phụ trợ đáng kể (tùy thuộc vào độ dài của iterable).
- itertools.dropwhile(predicate, iterable)¶
Tạo một trình vòng lặp loại bỏ các phần tử khỏi iterable trong khi predicate là đúng và sau đó trả về mọi phần tử. Gần tương đương với:
def dropwhile(vị ngữ, có thể lặp): # dropwhile(lambda x: x<5, [1,4,6,3,8]) → 6 3 8 iterator = iter(có thể lặp lại) cho x trong iterator: nếu không phải vị ngữ(x): năng suất x phá vỡ cho x trong iterator: năng suất x
Lưu ý rằng điều này không tạo ra đầu ra any cho đến khi vị từ đầu tiên trở thành sai, vì vậy itertool này có thể có thời gian khởi động dài.
- itertools.filterfalse(predicate, iterable)¶
Tạo một trình lặp để lọc các phần tử từ iterable chỉ trả về những phần tử mà predicate trả về giá trị sai. Nếu predicate là
None, trả về các mục sai. Gần tương đương với:def filterfalse(vị ngữ, có thể lặp): # filterfalse(lambda x: x<5, [1,4,6,3,8]) → 6 8 nếu vị ngữ là Không có: vị ngữ = bool cho x trong lần lặp: nếu không phải vị ngữ(x): năng suất x
- itertools.groupby(iterable, key=None)¶
Tạo một trình vòng lặp trả về các khóa và nhóm liên tiếp từ iterable. Zz002zz là một hàm tính toán giá trị khóa cho từng phần tử. Nếu không được chỉ định hoặc là
None, key sẽ mặc định là hàm nhận dạng và trả về phần tử không thay đổi. Nói chung, iterable cần phải được sắp xếp trên cùng một hàm khóa.Hoạt động của
groupby()tương tự như bộ lọcuniqtrong Unix. Nó tạo ra một điểm ngắt hoặc nhóm mới mỗi khi giá trị của hàm khóa thay đổi (đó là lý do tại sao thường cần phải sắp xếp dữ liệu bằng cách sử dụng cùng một hàm khóa). Hành vi đó khác với GROUP BY của SQL tổng hợp các phần tử phổ biến bất kể thứ tự đầu vào của chúng.Nhóm được trả về chính là một trình vòng lặp chia sẻ khả năng lặp cơ bản với
groupby(). Vì nguồn được chia sẻ nên khi đối tượnggroupby()được nâng cao, nhóm trước đó sẽ không còn hiển thị nữa. Vì vậy, nếu sau này cần dữ liệu đó, nó sẽ được lưu trữ dưới dạng danh sáchnhóm = [] phím duy nhất = [] dữ liệu = được sắp xếp (dữ liệu, key=keyfunc) cho k, g trong nhómby(data, keyfunc): Groups.append(list(g)) # Store nhóm iterator dưới dạng danh sách Uniquekeys.append(k)
groupby()gần tương đương với:def groupby(iterable, key=None): # [k for k, g in groupby('AAAABBBCCDAABBB')] → A B C D A B # [list(g) for k, g in groupby('AAAABBBCCD')] → AAAA BBB CC D keyfunc = (lambda x: x) nếu khóa là Không có khóa nào khác iterator = iter(có thể lặp lại) kiệt sức = Sai def _grouper(target_key): giá trị curr_value không cục bộ, curr_key, đã cạn kiệt mang lại giá trị curr_value cho curr_value trong iterator: curr_key = keyfunc(curr_value) nếu curr_key != target_key: trở về mang lại giá trị curr_value kiệt sức = Đúng thử: curr_value = next(iterator) ngoại trừ StopIteration: trở về curr_key = keyfunc(curr_value) trong khi chưa kiệt sức: target_key = Curr_key curr_group = _grouper(target_key) mang lại curr_key, curr_group nếu curr_key == target_key: cho _ trong Curr_group: vượt qua
- itertools.islice(iterable, stop)¶
- itertools.islice(iterable, start, stop[, step])
Tạo một trình lặp trả về các phần tử đã chọn từ iterable. Hoạt động giống như cắt chuỗi nhưng không hỗ trợ các giá trị âm cho start, stop hoặc step.
Nếu start bằng 0 hoặc
None, quá trình lặp bắt đầu từ 0. Nếu không, các phần tử từ iterable sẽ bị bỏ qua cho đến khi đạt đến start.Nếu stop là
None, quá trình lặp lại tiếp tục cho đến khi hết đầu vào, nếu có. Nếu không, nó sẽ dừng ở vị trí đã chỉ định.Nếu step là
Nonethì bước này mặc định là một. Các phần tử được trả về liên tiếp trừ khi step được đặt cao hơn một phần tử dẫn đến các mục bị bỏ qua.Gần tương đương với:
def islice(iterable, *args): # islice('ABCDEFG', 2) → A B # islice('ABCDEFG', 2, 4) → C D # islice('ABCDEFG', 2, None) → C D E F G # islice('ABCDEFG', 0, None, 2) → A C E G s = lát(*args) start = 0 nếu s.start là Không có gì khác s.start dừng = s.stop step = 1 nếu s.step không có gì khác s.step nếu bắt đầu < 0 hoặc (dừng không phải là Không và dừng < 0) hoặc bước <= 0: tăng giá trịError chỉ số = count() nếu điểm dừng là Không có phạm vi nào khác (max(start, stop)) tiếp theo_i = bắt đầu đối với i, phần tử trong zip(chỉ số, có thể lặp): nếu tôi == next_i: yếu tố năng suất bước tiếp theo_i +=
Nếu đầu vào là một trình lặp, thì việc sử dụng hoàn toàn islice sẽ nâng trình lặp đầu vào lên từng bước
max(start, stop)bất kể giá trị step.
- itertools.pairwise(iterable)¶
Trả về các cặp chồng chéo liên tiếp được lấy từ iterable đầu vào.
Số lượng 2 bộ dữ liệu trong trình vòng lặp đầu ra sẽ ít hơn một số lượng đầu vào. Nó sẽ trống nếu lần lặp đầu vào có ít hơn hai giá trị.
Gần tương đương với:
def theo cặp (lặp lại): # pairwise('ABCDEFG') → AB BC CD DE EF FG iterator = iter(có thể lặp lại) a = next(iterator, None) cho b trong iterator: mang lại a, b a = b
Added in version 3.10.
- itertools.permutations(iterable, r=None)¶
Trả về độ dài r liên tiếp permutations of elements từ iterable.
Nếu r không được chỉ định hoặc là
Nonethì r sẽ mặc định có độ dài của iterable và tất cả các hoán vị độ dài đầy đủ có thể có sẽ được tạo.Đầu ra là một dãy con của
product()trong đó các mục có phần tử lặp lại đã được lọc ra. Độ dài của đầu ra được cho bởimath.perm(), tính toánn! / (n - r)!khi0 ≤ r ≤ nhoặc 0 khir > n.Các bộ hoán vị được phát ra theo thứ tự từ điển theo thứ tự của iterable đầu vào. Nếu iterable đầu vào được sắp xếp, các bộ dữ liệu đầu ra sẽ được tạo theo thứ tự được sắp xếp.
Các phần tử được coi là duy nhất dựa trên vị trí của chúng chứ không phải giá trị của chúng. Nếu các phần tử đầu vào là duy nhất thì sẽ không có giá trị lặp lại trong một hoán vị.
Gần tương đương với:
hoán vị def(iterable, r=None): # permutations('ABCD', 2) → AB AC AD BA BC BD CA CB CD DA DB DC # permutations(phạm vi (3)) → 012 021 102 120 201 210 pool = tuple(lặp lại) n = len(pool) r = n nếu r là Không có gì khác r nếu r > n: trở về chỉ số = danh sách (phạm vi (n)) chu kỳ = danh sách (phạm vi (n, n-r, -1)) mang lại tuple(pool[i] cho i trong chỉ số[:r]) trong khi n: vì tôi ở vị trí đảo ngược(range(r)): chu kỳ[i] -= 1 nếu chu kỳ [i] == 0: chỉ số[i:] = chỉ số[i+1:] + chỉ số[i:i+1] chu kỳ[i] = n - i khác: j = chu kỳ[i] chỉ số[i], chỉ số[-j] = chỉ số[-j], chỉ số[i] mang lại tuple(pool[i] cho i trong chỉ số[:r]) phá vỡ khác: trở về
- itertools.product(*iterables, repeat=1)¶
Cartesian product của các lần lặp đầu vào.
Gần tương đương với các vòng lặp for lồng nhau trong biểu thức trình tạo. Ví dụ:
product(A, B)trả về giống như((x,y) for x in A for y in B).Các vòng lặp lồng nhau quay vòng giống như một đồng hồ đo đường với phần tử ngoài cùng bên phải tiến lên sau mỗi lần lặp. Mẫu này tạo ra một thứ tự từ điển để nếu các vòng lặp của đầu vào được sắp xếp thì các bộ sản phẩm sẽ được xuất ra theo thứ tự được sắp xếp.
Để tính tích của một lần lặp với chính nó, hãy chỉ định số lần lặp lại bằng đối số từ khóa repeat tùy chọn. Ví dụ:
product(A, repeat=4)có nghĩa giống nhưproduct(A, A, A, A).Hàm này gần tương đương với đoạn mã sau, ngoại trừ việc triển khai thực tế không tạo ra các kết quả trung gian trong bộ nhớ:
sản phẩm def(*iterables,repeat=1): # product('ABCD', 'xy') → Axe Ay Bx Bởi Cx Cy Dx Dy # product(phạm vi(2), lặp lại=3) → 000 001 010 011 100 101 110 111 nếu lặp lại < 0: raise ValueError('đối số lặp lại không thể âm') pool = [tuple(pool) cho nhóm trong các lần lặp] * lặp lại kết quả = [[]] cho hồ bơi trong hồ bơi: result = [x+[y] for x in result for y in pool] cho kết quả sản phẩm: sản lượng tuple(prod)
Trước khi
product()chạy, nó sử dụng hoàn toàn các lần lặp đầu vào, giữ các nhóm giá trị trong bộ nhớ để tạo ra sản phẩm. Theo đó, nó chỉ hữu ích với đầu vào hữu hạn.
- itertools.repeat(object[, times])¶
Tạo một trình vòng lặp trả về object nhiều lần. Chạy vô thời hạn trừ khi đối số times được chỉ định.
Gần tương đương với:
def lặp lại (đối tượng, lần = Không): # repeat(10, 3) → 10 10 10 nếu thời gian là Không có: trong khi Đúng: đối tượng năng suất khác: cho tôi trong phạm vi (lần): đối tượng năng suất
Cách sử dụng phổ biến của repeat là cung cấp một luồng giá trị không đổi cho map hoặc zip:
>>> danh sách(map(pow, phạm vi(10), lặp lại(2))) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- itertools.starmap(function, iterable)¶
Tạo một trình vòng lặp tính toán function bằng cách sử dụng các đối số thu được từ iterable. Được sử dụng thay cho
map()khi các tham số đối số đã được "nén trước" thành bộ dữ liệu.Sự khác biệt giữa
map()vàstarmap()tương đương với sự khác biệt giữafunction(a,b)vàfunction(*c). Gần tương đương với:def starmap(hàm, có thể lặp): # starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000 cho các đối số trong iterable: hàm năng suất(*args)
- itertools.takewhile(predicate, iterable)¶
Tạo một trình vòng lặp trả về các phần tử từ iterable miễn là predicate là đúng. Gần tương đương với:
def mất thời gian (vị ngữ, có thể lặp lại): # takewhile(lambda x: x<5, [1,4,6,3,8]) → 1 4 cho x trong lần lặp: nếu không phải vị ngữ(x): phá vỡ năng suất x
Lưu ý, phần tử đầu tiên không đạt điều kiện vị ngữ sẽ được sử dụng từ trình vòng lặp đầu vào và không có cách nào để truy cập nó. Đây có thể là một vấn đề nếu một ứng dụng muốn sử dụng thêm trình vòng lặp đầu vào sau khi takewhile đã chạy hết. Để giải quyết vấn đề này, thay vào đó hãy cân nhắc sử dụng more-itertools before_and_after().
- itertools.tee(iterable, n=2)¶
Trả về các trình vòng lặp độc lập n từ một vòng lặp duy nhất.
Gần tương đương với:
def tee(lặp đi lặp lại, n=2): nếu n < 0: tăng giá trịError nếu n == 0: trở lại () iterator = _tee(lặp đi lặp lại) kết quả = [trình vòng lặp] cho _ trong phạm vi (n - 1): result.append(_tee(iterator)) trả về bộ dữ liệu (kết quả) lớp _tee: def __init__(tự, có thể lặp lại): it = iter(có thể lặp lại) nếu isinstance(it, _tee): self.iterator = it.iterator self.link = it.link khác: self.iterator = nó self.link = [Không có, Không có] chắc chắn __iter__(tự): tự trở về chắc chắn __next__(tự): liên kết = self.link nếu liên kết [1] là Không có: link[0] = next(self.iterator) liên kết[1] = [Không có, Không có] giá trị, self.link = liên kết giá trị trả về
Khi iterable đầu vào đã là một đối tượng lặp tee, tất cả các thành viên của bộ dữ liệu trả về được xây dựng như thể chúng được tạo ra bởi lệnh gọi
tee()ngược dòng. "Bước làm phẳng" này cho phép các lệnh gọitee()lồng nhau chia sẻ cùng một chuỗi dữ liệu cơ bản và có một bước cập nhật duy nhất thay vì một chuỗi lệnh gọi.Thuộc tính làm phẳng làm cho các trình vòng lặp tee có thể nhìn thấy một cách hiệu quả:
nhìn về phía trước (tee_iterator): "Trả về giá trị tiếp theo mà không di chuyển đầu vào về phía trước" [forked_iterator] = tee(tee_iterator, 1) quay lại tiếp theo(forked_iterator)
>>> iterator = iter('abcdef') >>> [iterator] = tee(iterator, 1) # Make đầu vào có thể nhìn thấy được >>> next(iterator) # Move trình lặp chuyển tiếp 'a' >>> lookahead(iterator) # Check giá trị tiếp theo 'b' >>> tiếp theo(iterator) # Continue tiến về phía trước 'b'
Các trình vòng lặp
teekhông an toàn cho luồng. MộtRuntimeErrorcó thể được tăng lên khi sử dụng đồng thời các trình vòng lặp được trả về bởi cùng một lệnh gọitee(), ngay cả khi iterable ban đầu là luồng an toàn.Itertool này có thể yêu cầu bộ nhớ phụ đáng kể (tùy thuộc vào lượng dữ liệu tạm thời cần được lưu trữ). Nói chung, nếu một trình vòng lặp sử dụng hầu hết hoặc tất cả dữ liệu trước khi một trình vòng lặp khác khởi động thì việc sử dụng
list()thay vìtee()sẽ nhanh hơn.
- itertools.zip_longest(*iterables, fillvalue=None)¶
Tạo một trình vòng lặp tổng hợp các phần tử từ mỗi iterables.
Nếu các lần lặp có độ dài không đồng đều, các giá trị còn thiếu sẽ được điền bằng fillvalue. Nếu không được chỉ định, fillvalue mặc định là
None.Việc lặp lại tiếp tục cho đến khi hết lượt lặp dài nhất.
Gần tương đương với:
def zip_longest(*iterables, fillvalue=None): # zip_longest('ABCD', 'xy', fillvalue='-') → Axe Bởi C- D- iterators = list(map(iter, iterables)) num_active = len(iterators) nếu không phải num_active: trở về trong khi Đúng: giá trị = [] đối với i, iterator trong enumerate(iterators): thử: giá trị = tiếp theo(iterator) ngoại trừ StopIteration: num_active -= 1 nếu không phải num_active: trở về iterators[i] = lặp lại (giá trị điền) giá trị = giá trị điền giá trị.append(giá trị) mang lại bộ dữ liệu (giá trị)
Nếu một trong các lần lặp có khả năng là vô hạn thì hàm
zip_longest()phải được bọc bằng thứ gì đó giới hạn số lượng lệnh gọi (ví dụ:islice()hoặctakewhile()).
Bí quyết Itertools¶
Phần này hiển thị các công thức để tạo một bộ công cụ mở rộng bằng cách sử dụng itertools hiện có làm khối xây dựng.
Mục đích chính của công thức nấu ăn itertools là mang tính giáo dục. Các công thức nấu ăn cho thấy nhiều cách suy nghĩ khác nhau về từng công cụ — ví dụ: chain.from_iterable có liên quan đến khái niệm làm phẳng. Các công thức nấu ăn cũng đưa ra ý tưởng về cách kết hợp các công cụ — ví dụ: cách starmap() và repeat() có thể hoạt động cùng nhau. Các công thức nấu ăn cũng hiển thị các mẫu sử dụng itertool với mô-đun operator và collections cũng như với các itertools tích hợp sẵn như map(), filter(), reversed() và enumerate().
Mục đích thứ yếu của các công thức nấu ăn là phục vụ như một vườn ươm. Các itertools accumulate(), compress() và pairwise() ban đầu là công thức nấu ăn. Hiện tại, các công thức sliding_window(), derangements() và sieve() đang được thử nghiệm để xem liệu chúng có chứng minh được giá trị của mình hay không.
Về cơ bản, tất cả các công thức này và rất nhiều công thức khác có thể được cài đặt từ dự án more-itertools được tìm thấy trên Python Package Index:
python -m pip cài đặt thêm itertools
Nhiều công thức nấu ăn mang lại hiệu suất cao tương tự như bộ công cụ cơ bản. Hiệu suất bộ nhớ vượt trội được duy trì bằng cách xử lý từng phần tử một thay vì đưa toàn bộ phần tử có thể lặp lại vào bộ nhớ cùng một lúc. Khối lượng mã được giữ ở mức nhỏ bằng cách liên kết các công cụ với nhau trong functional style. Tốc độ cao được duy trì bằng cách ưu tiên các khối xây dựng "được vector hóa" hơn là sử dụng vòng lặp for và generators vốn phát sinh chi phí cho trình thông dịch.
từ nhập itertools (tích lũy, theo đợt, chuỗi, kết hợp, nén,
đếm, chu kỳ, lọc sai, nhóm, islice, hoán vị, tích,
lặp lại, bản đồ sao, tee, zip_longest)
từ bộ sưu tập nhập Bộ đếm, deque
từ ngăn chặn nhập ngữ cảnh
từ nhập functools giảm
từ lược nhập toán học, isqrt, prod, sumprod
từ toán tử nhập getitem, is_not, itemgetter, mul, neg, truediv
# ==== Một lớp lót cơ bản ====
def take(n, iterable):
"Trả về n mục đầu tiên của iterable dưới dạng danh sách."
danh sách trả về(islice(iterable, n))
trả trước def (giá trị, có thể lặp):
"Thêm một giá trị vào trước một giá trị có thể lặp lại."
# prepend(1, [2, 3, 4]) → 1 2 3 4
chuỗi trả về([giá trị], có thể lặp lại)
chắc chắn đang chạy_mean (có thể lặp lại):
"Cho kết quả trung bình của tất cả các giá trị được thấy cho đến nay."
# running_mean([8,5, 9,5, 7,5, 6,5]) → 8,5 9,0 8,5 8,0
trả về bản đồ (truediv, tích lũy (lặp lại), đếm (1))
def Repeatfunc(function, Times=None, *args):
"Lặp lại lệnh gọi đến một hàm với các đối số được chỉ định."
nếu thời gian là Không có:
trả về starmap(hàm, lặp lại(args))
trả về starmap(hàm, lặp lại(args, lần))
def làm phẳng (list_of_lists):
"Làm phẳng một cấp độ lồng nhau."
chuỗi trả về.from_iterable(list_of_lists)
def ncycles(iterable, n):
"Trả về các phần tử chuỗi n lần."
return chain.from_iterable(repeat(tuple(iterable), n))
vòng lặp def (n):
"Lặp n lần. Giống như phạm vi (n) nhưng không tạo số nguyên."
# for _ trong vòng lặp(100): ...
lặp lại lặp lại(Không, n)
đuôi def(n, có thể lặp):
"Trả về một trình vòng lặp cho n mục cuối cùng."
# tail(3, 'ABCDEFG') → E F G
trả về iter(deque(iterable, maxlen=n))
def tiêu thụ(iterator, n=None):
"Tiến lên n bước của trình vòng lặp. Nếu n là Không, hãy tiêu thụ hoàn toàn."
Các hàm # Use tiêu thụ các vòng lặp ở tốc độ C.
nếu n là Không:
deque(iterator, maxlen=0)
khác:
tiếp theo(islice(iterator, n, n), Không có)
def thứ n(iterable, n, default=None):
"Trả về mục thứ n hoặc giá trị mặc định."
return next(islice(iterable, n, None), mặc định)
định lượng def (lặp lại, vị ngữ=bool):
"Cho một vị từ trả về Đúng hoặc Sai, hãy đếm kết quả Đúng."
tổng trả về (bản đồ (vị ngữ, có thể lặp lại))
def first_true(iterable, default=False, predicate=None):
"Trả về giá trị thực đầu tiên hoặc *default* nếu không có giá trị thực."
# first_true([a, b, c], x) → a hoặc b hoặc c hoặc x
# first_true([a, b], x, f) → a if f(a) else b if f(b) else x
return next(filter(predicate, iterable), mặc định)
def all_equal(iterable, key=None):
"Trả về True nếu tất cả các phần tử đều bằng nhau."
# all_equal('4٤௪౪໔', key=int) → Đúng
trả về len(take(2, groupby(iterable, key))) <= 1
# ==== Đường ống dữ liệu ====
def Unique_justseen(iterable, key=None):
"Tạo ra các phần tử độc đáo, giữ nguyên trật tự. Chỉ nhớ phần tử vừa nhìn thấy."
# unique_justseen('AAAABBBCCDAABBB') → A B C D A B
# unique_justseen('ABBcCAD', str.casefold) → A B c A D
nếu khóa là Không:
return map(itemgetter(0), groupby(iterable))
return map(next, map(itemgetter(1), groupby(iterable, key)))
def Unique_everseen(iterable, key=None):
"Tạo ra các yếu tố độc đáo, giữ nguyên trật tự. Ghi nhớ tất cả các yếu tố từng thấy."
# unique_everseen('AAAABBBCCDAABBB') → A B C D
# unique_everseen('ABBcCAD', str.casefold) → A B c D
đã thấy = set()
nếu khóa là Không:
đối với phần tử trong filterfalse(seen.__contains__, iterable):
đã thấy.add (phần tử)
yếu tố năng suất
khác:
cho phần tử trong iterable:
k = khóa (phần tử)
nếu k không thấy:
đã thấy.add(k)
yếu tố năng suất
def duy nhất(iterable, key=None, Reverse=False):
"Tạo ra các phần tử duy nhất theo thứ tự được sắp xếp. Hỗ trợ các đầu vào không thể băm được."
# unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4]
tuần tự = được sắp xếp (lặp lại, key=key, đảo ngược=đảo ngược)
trả về Unique_justseen(theo trình tự, key=key)
def trượt_window (lặp lại, n):
"Thu thập dữ liệu thành các khối hoặc khối có độ dài cố định chồng lên nhau."
# sliding_window('ABCDEFG', 3) → ABC BCD CDE DEF EFG
iterator = iter(có thể lặp lại)
window = deque(islice(iterator, n - 1), maxlen=n)
cho x trong iterator:
window.append(x)
mang lại tuple(cửa sổ)
def grouper(iterable, n, *,complete='fill', fillvalue=None):
"Thu thập dữ liệu thành các khối hoặc khối có độ dài cố định không chồng chéo."
# grouper('ABCDEFG', 3, fillvalue='x') → ABC DEF Gxx
# grouper('ABCDEFG', 3, không đầy đủ='nghiêm ngặt') → ABC DEF ValueError
# grouper('ABCDEFG', 3, chưa hoàn thành='bỏ qua') → ABC DEF
trình vòng lặp = [iter(iterable)] * n
trận đấu không đầy đủ:
trường hợp 'điền':
trả về zip_longest(*iterators, fillvalue=fillvalue)
trường hợp 'nghiêm ngặt':
trả về zip(*iterators, strict=True)
trường hợp 'bỏ qua':
trả về zip(*iterators)
trường hợp _:
raise ValueError('Dự kiến điền, nghiêm ngặt hoặc bỏ qua')
def roundrobin(*iterables):
"Truy cập các lần lặp đầu vào trong một chu kỳ cho đến khi hết từng lần."
# roundrobin('ABC', 'D', 'EF') → A D E B F C
# Algorithm được ghi có vào George Sakkis
vòng lặp = bản đồ(iter, iterables)
cho num_active trong phạm vi(len(iterables), 0, -1):
iterators = chu kỳ(islice(iterators, num_active))
mang lại lợi nhuận từ bản đồ (tiếp theo, vòng lặp)
phần con def(seq):
"Trả về tất cả các phần con không trống liền kề của một chuỗi."
# subslices('ABCD') → A AB ABC ABCD B BC BCD C CD D
lát = starmap(lát, kết hợp(phạm vi(len(seq) + 1), 2))
bản đồ trả về (getitem, lặp lại (seq), lát)
sự xáo trộn của def(iterable, r=None):
"Tạo hoán vị độ dài r không có điểm cố định."
# derangements('ABCD') → BADC BCDA BDAC CADB CDAB CDBA DABC DCAB DCBA
# Algorithm được ghi nhận cho Stefan Pochmann
seq = tuple(lặp lại)
pos = tuple(range(len(seq)))
has_moved = map(map, lặp lại(is_not), lặp lại(pos), hoán vị(pos, r=r))
valid_derangements = bản đồ (tất cả, has_moved)
trả về nén(hoán vị(seq, r=r), valid_derangements)
def iter_index(iterable, value, start=0, stop=None):
"Trả về các chỉ số trong đó một giá trị xuất hiện theo trình tự hoặc có thể lặp lại."
# iter_index('AABCADEAF', 'A') → 0 1 4 7
seq_index = getattr(iterable, 'index', None)
nếu seq_index là Không có:
iterator = islice(iterable, start, stop)
đối với i, phần tử trong enumerate(iterator, start):
nếu phần tử là giá trị hoặc phần tử == giá trị:
nhường tôi
khác:
stop = len(iterable) nếu dừng là Không có gì khác dừng
tôi = bắt đầu
với triệt tiêu (ValueError):
trong khi Đúng:
năng suất (i := seq_index(giá trị, i, dừng))
tôi += 1
def iter_Exception(hàm, ngoại lệ, đầu tiên=Không):
"Chuyển đổi giao diện gọi cho đến khi ngoại lệ thành giao diện lặp."
# iter_except(d.popitem, KeyError) → trình lặp từ điển không chặn
với triệt tiêu (ngoại lệ):
nếu đầu tiên không phải là Không có:
mang lại đầu tiên()
trong khi Đúng:
hàm năng suất()
# ==== Các phép toán ====
def đa thức(*đếm):
"Số cách sắp xếp riêng biệt của nhiều tập hợp."
# Counter('abracadabra').values() → 5 2 2 1 1
# multinomial(5, 2, 2, 1, 1) → 83160
trả về sản phẩm (bản đồ (lược, tích lũy (đếm), đếm))
sức mạnh def (lặp lại):
"Các chuỗi lặp lại từ ngắn nhất đến dài nhất."
# powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)
s = danh sách (lặp lại)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
def sum_of_squares(lặp lại):
" Cộng các bình phương của các giá trị đầu vào."
# sum_of_squares([10, 20, 30]) → 1400
trả về sumprod(*tee(iterable))
# ==== Các phép toán ma trận ====
định hình lại def (ma trận, cột):
"Định hình lại ma trận 2-D để có số cột nhất định."
# reshape([(0, 1), (2, 3), (4, 5)], 3) → (0, 1, 2) (3, 4, 5)
trả về theo đợt(chain.from_iterable(matrix), columns, strict=True)
chuyển vị def (ma trận):
"Hoán đổi hàng và cột của ma trận 2-D."
# transpose([(1, 2, 3), (11, 22, 33)]) → (1, 11) (2, 22) (3, 33)
trả về zip(*ma trận, strict=True)
def matmul(m1, m2):
"Nhân hai ma trận."
# matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) → (49, 80) (41, 60)
n = len(m2[0])
trả về theo đợt(starmap(sumprod, sản phẩm(m1, transpose(m2))), n)
# ==== Số học đa thức ====
def convolve(tín hiệu, kernel):
"""Tích chập tuyến tính rời rạc của hai lần lặp.
Tương đương với phép nhân đa thức.
Tích chập có tính chất giao hoán về mặt toán học; tuy nhiên, đầu vào là
được đánh giá khác nhau. Tín hiệu được tiêu thụ một cách lười biếng và có thể
vô hạn. Hạt nhân được sử dụng hoàn toàn trước khi bắt đầu tính toán.
Bài viết: https://betterexplained.com/articles/intuitive-convolution/
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
"""
# convolve([1, -1, -20], [1, -3]) → 1 -4 -17 60
# convolve(dữ liệu, [0,25, 0,25, 0,25, 0,25]) → Trung bình di chuyển (mờ)
# convolve(data, [1/2, 0, -1/2]) → ước tính đạo hàm thứ nhất
# convolve(data, [1, -2, 1]) → ước tính đạo hàm thứ 2
kernel = tuple(kernel)[::-1]
n = len(hạt nhân)
độn_signal = chuỗi (lặp lại (0, n-1), tín hiệu, lặp lại (0, n-1))
windowed_signal = trượt_window(padd_signal, n)
bản đồ trả về (sumprod, lặp lại (kernel), windowed_signal)
def polynomial_from_roots(root):
"""Tính các hệ số của đa thức từ gốc của nó.
(x - 5) (x + 4) (x - 3) mở rộng thành: x³ -4x² -17x + 60
"""
# polynomial_from_roots([5, -4, 3]) → [1, -4, -17, 60]
các yếu tố = zip(lặp lại(1), bản đồ(neg, rễ))
danh sách trả về(giảm(convolve, thừa số, [1]))
def đa thức_eval(hệ số, x):
"""Đánh giá một đa thức ở một giá trị cụ thể.
Tính toán với độ ổn định số tốt hơn phương pháp Horner.
"""
# Evaluate x³ -4x² -17x + 60 tại x = 5
# polynomial_eval([1, -4, -17, 60], x=5) → 0
n = len(hệ số)
nếu không thì:
kiểu trả về(x)(0)
quyền hạn = bản đồ (pow, lặp lại (x), đảo ngược (phạm vi (n)))
trả về sumprod(hệ số, lũy thừa)
def đa thức_dẫn xuất(hệ số):
"""Tính đạo hàm bậc nhất của một đa thức.
f(x) = x³ -4x² -17x + 60
f'(x) = 3x² -8x -17
"""
# polynomial_derivative([1, -4, -17, 60]) → [3, -8, -17]
n = len(hệ số)
quyền hạn = đảo ngược (phạm vi (1, n))
danh sách trả về(map(mul, hệ số, lũy thừa))
# ==== Lý thuyết số ====
sàng def (n):
"Số nguyên tố nhỏ hơn n."
# sieve(30) → 2 3 5 7 11 13 17 19 23 29
nếu n > 2:
năng suất 2
dữ liệu = bytearray((0, 1)) * (n // 2)
cho p trong iter_index(data, 1, start=3, stop=isqrt(n) + 1):
dữ liệu[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
mang lại lợi nhuận từ iter_index(data, 1, start=3)
hệ số def (n):
"Các thừa số nguyên tố của n."
# factor(99) → 3 3 11
# factor(1_000_000_000_000_007) → 47 59 360620266859
# factor(1_000_000_000_000_403) → 1000000000000403
cho số nguyên tố trong sàng(isqrt(n) + 1):
trong khi không phải n % nguyên tố:
năng suất nguyên tố
n //= số nguyên tố
nếu n == 1:
trở về
nếu n > 1:
năng suất n
def is_prime(n):
"Trả về True nếu n là số nguyên tố."
# is_prime(1_000_000_000_000_403) → Đúng
trả về n > 1 và next(factor(n)) == n
toàn bộ def(n):
"Đếm các số tự nhiên đến n là nguyên tố cùng nhau với n."
# zz004zz
# totient(12) → 4 vì len([1, 5, 7, 11]) == 4
cho số nguyên tố trong tập hợp(yếu tố(n)):
n -= n // số nguyên tố
trả lại n