Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Python

Hàm Python tạo iterator cho vòng lặp hiệu quả (itertools)


Giống như hầu hết các ngôn ngữ lập trình, Python cung cấp câu lệnh while và for để tạo cấu trúc vòng lặp. Câu lệnh for đặc biệt hữu ích để duyệt qua các đối tượng lặp được (iterable) như danh sách, tuple hoặc chuỗi. Các công cụ lặp hiệu quả và nhanh hơn được định nghĩa trong mô-đun itertools của thư viện chuẩn Python. Các khối xây dựng iterator này là triển khai Pythonic của các công cụ tương tự trong các ngôn ngữ lập trình hàm như Haskell và SML.

Các hàm trong mô-đun itertools có ba loại:

  • Iterator vô hạn (Infinite iterators)
  • Iterator hữu hạn (Finite iterators)
  • Iterator tổ hợp (Combinatoric iterators)

Các hàm sau tạo ra các chuỗi vô hạn:

count() - Hàm này trả về một iterator các giá trị cách đều nhau từ giá trị bắt đầu. Hàm có thể có giá trị bước (step) tùy chọn để tăng giá trị liên tiếp theo khoảng cách này.

>>> from itertools import count
>>> for x in count(20):
...     print(x)
>>> for x in count(100, 10):
...     print(x)

Câu lệnh đầu tiên sẽ tạo chuỗi vô hạn bắt đầu từ 20 và cái thứ hai sẽ tạo số từ 100 với tần suất bước 10. Lưu ý rằng các vòng lặp là vô hạn và sẽ không tự kết thúc. Chúng sẽ bị kết thúc bằng cách nhấn Ctrl-C.

cycle() - Hàm này bắt đầu trả về từng phần tử từ iterable cho trước và lưu bản sao của nó. Khi các phần tử cạn kiệt, các phần tử trong bản sao lưu được trả về do đó tạo thành vòng lặp vô hạn.

>>> from itertools import cycle
>>> for x in cycle("hello"):
...     print(x)

Các ký tự trong chuỗi sẽ được in lặp lại cho đến khi ngắt bàn phím Ctrl-C được đưa ra.

repeat() - Hàm này trả về đối số đối tượng liên tục. Nếu đối số thứ hai times được cung cấp, lặp lại diễn ra nhiều lần đó.

>>> from itertools import repeat
>>> for x in repeat(1):
...     print(x)
>>> for x in repeat('hello', 10):
...     print(x)

Vòng lặp đầu tiên sẽ in 1 vô tận. Cái thứ hai in 'hello' 10 lần.

Các hàm trong danh mục sau trả về iterator hữu hạn kết thúc trên chuỗi đầu vào ngắn nhất.

accumulate() - Hàm này có hai tham số. Tham số đầu tiên là một iterable (danh sách, tuple hoặc chuỗi). Tham số thứ hai mặc định là operator.add() (hàm trong mô-đun operator triển khai toán tử cộng chuẩn), nhưng có thể là bất kỳ hàm nào khác nhận hai tham số số.

accumulate(sequence, func)

Hai phần tử đầu tiên của chuỗi đầu vào được xử lý bởi func. Kết quả của quá trình xử lý là tham số đầu tiên cho lần lặp tiếp theo và tham số thứ hai cho func là phần tử thứ ba trong chuỗi đầu vào. Quá trình này lặp lại cho đến khi chuỗi cạn kiệt. Hàm accumulate trả về một iterator trong đó mỗi phần tử là kết quả tích lũy của việc xử lý các phần tử liên tiếp.

Trong ví dụ sau, các số trong danh sách được cộng dồn. Lưu ý rằng đối số hàm mặc định là phép cộng.

>>> from itertools import accumulate
>>> list(accumulate([1, 2, 3, 4, 5]))
[1, 3, 6, 10, 15]

Chúng ta có thể có hàm do người dùng định nghĩa làm tham số thứ hai cho hàm accumulate():

>>> def multiply(x, y):
...     return x * y
>>> list(accumulate([1, 2, 3, 4, 5], multiply))
[1, 2, 6, 24, 120]

Hành vi này hơi tương tự hàm tích hợp sẵn reduce(). Hàm reduce() chỉ trả về kết quả cuối cùng của sự tích lũy, trong khi accumulate() xây dựng iterator của tất cả các kết quả trung gian.

chain() - Hàm này có thể có nhiều hơn một iterable làm tham số. Nó trả về từng phần tử của iterable đầu tiên vào iterator kết quả và chuyển sang iterable tiếp theo cho đến khi các tham số iterable cạn kiệt.

>>> from itertools import chain
>>> list(chain([10, 20], 'hello', range(4)))
[10, 20, 'h', 'e', 'l', 'l', 'o', 0, 1, 2, 3]

dropwhile() - Hàm này trả về một iterator bằng cách loại bỏ các phần tử từ iterable miễn là hàm vị từ (predicate) trả về true. Ngay khi hàm trả về false, tất cả các phần tử còn lại được sản xuất cho iterator.

>>> from itertools import dropwhile
>>> def iseven(x):
...     if x % 2 == 0:
...         return True
...     else:
...         return False
>>> list(dropwhile(iseven, [12, 90, 61, 4, 15]))
[61, 4, 15]

filterfalse() - Hàm này trả về một iterator bằng cách lọc bỏ các phần tử mà hàm vị từ cho kết quả False.

>>> from itertools import filterfalse
>>> def iseven(x):
...     if x % 2 == 0:
...         return True
...     else:
...         return False
>>> list(filterfalse(iseven, [12, 90, 61, 4, 15]))
[61, 15]

islice() - Hàm này xây dựng một iterator bằng cách chọn các phần tử nhất định từ iterable. Tiêu chí lựa chọn phụ thuộc vào tham số start, stop và step. Lựa chọn bắt đầu từ giá trị start và tiếp tục đến giá trị stop. Nếu stop là None, nó đi đến cuối iterable, nếu không lựa chọn dừng tại chỉ số chỉ định. Tham số step mặc định là 1. Lựa chọn các phần tử tăng theo tham số step. Không tham số nào có thể là âm.

>>> from itertools import islice
>>> list(islice(range(10), 1, 5, 2))
[1, 3]
>>> list(islice(range(10), 0, None, 3))
[0, 3, 6, 9]
>>> list(islice(range(10), 5, None))
[5, 6, 7, 8, 9]
>>> list(islice(range(10), 5))
[0, 1, 2, 3, 4]

Các hàm sau tạo iterator tổ hợp từ các đối tượng iterable:

product() - Hàm này tạo một iterator là tích Descartes của các phần tử trong chuỗi đầu vào. Điều này tương đương với việc xây dựng các vòng lặp for lồng nhau, một cho việc duyệt từng chuỗi iterable.

Trong ví dụ sau, kỹ thuật list comprehension được dùng để chạy hai vòng lặp lồng nhau trên hai chuỗi để xây dựng tích Descartes.

>>> [[x, y] for x in [1, 2, 3] for y in ['a', 'b', 'c']]
[[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c'], [3, 'a'], [3, 'b'], [3, 'c']]

Hàm product() tạo kết quả tương tự:

>>> from itertools import product
>>> list(product([1, 2, 3], ['a', 'b', 'c']))
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]

permutations() - Hàm này tạo ra tất cả các hoán vị có thể của các phần tử trong iterable đầu vào. Độ dài của mỗi hoán vị có thể được chỉ định làm tham số thứ hai cho hàm này. Nếu không chỉ định, độ dài là một.

>>> list(permutations(range(1, 4), 2))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

combinations() - Hàm này tạo ra tất cả các tổ hợp có thể của các phần tử trong iterable đầu vào. Độ dài của mỗi hoán vị có thể được chỉ định làm tham số thứ hai cho hàm này. Nếu không chỉ định, độ dài là một.

>>> from itertools import combinations
>>> list(combinations(range(1, 4), 2))
[(1, 2), (1, 3), (2, 3)]

Bài viết này giới thiệu các công cụ iterator được định nghĩa trong mô-đun itertools của thư viện Python.