bởi Radu Raicea

máy phát điện đã là một phần quan trọng của Python kể từ khi chúng được giới thiệu với PEP 255.
Các hàm trình tạo cho phép bạn khai báo một hàm hoạt động giống như một trình vòng lặp.
Chúng cho phép các lập trình viên tạo một trình vòng lặp một cách nhanh chóng, dễ dàng và rõ ràng.
Bạn có thể hỏi một iterator là gì?
Một trình vòng lặp là một đối tượng có thể được lặp lại (lặp đi lặp lại). Nó được sử dụng để trừu tượng hóa một vùng chứa dữ liệu để làm cho nó hoạt động giống như một đối tượng có thể lặp lại. Bạn có thể đã sử dụng một số đối tượng có thể lặp lại hàng ngày: chuỗi, danh sách và từ điển để đặt tên cho một số đối tượng.
Một trình vòng lặp được định nghĩa bởi một lớp thực hiện Giao thức lặp. Giao thức này tìm kiếm hai phương thức trong lớp: __iter__
và __next__
.
Nào, lùi lại. Tại sao bạn thậm chí muốn tạo các trình vòng lặp?
Tiết kiệm dung lượng bộ nhớ
Trình vòng lặp không tính toán giá trị của từng mục khi được khởi tạo. Họ chỉ tính toán khi bạn yêu cầu. Điều này được gọi là đánh giá lười biếng.
Đánh giá chậm rất hữu ích khi bạn có một tập dữ liệu rất lớn để tính toán. Nó cho phép bạn bắt đầu sử dụng dữ liệu ngay lập tức, trong khi toàn bộ tập dữ liệu đang được tính toán.
Giả sử chúng ta muốn lấy tất cả các số nguyên tố nhỏ hơn một số lớn nhất.
Đầu tiên chúng ta xác định hàm kiểm tra xem một số có phải là số nguyên tố hay không:
def check_prime(number): for divisor in range(2, int(number ** 0.5) + 1): if number % divisor == 0: return False return True
Sau đó, chúng tôi xác định lớp iterator sẽ bao gồm __iter__
và __next__
phương pháp:
class Primes: def __init__(self, max): self.max = max self.number = 1
def __iter__(self): return self
def __next__(self): self.number += 1 if self.number >= self.max: raise StopIteration elif check_prime(self.number): return self.number else: return self.__next__()
Primes
được khởi tạo với một giá trị tối đa. Nếu số nguyên tố tiếp theo lớn hơn hoặc bằng số max
iterator sẽ tăng một StopIteration
ngoại lệ, kết thúc trình vòng lặp.
Khi chúng tôi yêu cầu phần tử tiếp theo trong trình vòng lặp, nó sẽ tăng dần number
bằng 1 và kiểm tra xem đó có phải là số nguyên tố hay không. Nếu không, nó sẽ gọi __next__
một lần nữa cho đến khi number
là nguyên tố. Khi đã xong, trình lặp sẽ trả về số.
Bằng cách sử dụng trình vòng lặp, chúng tôi không tạo danh sách các số nguyên tố trong bộ nhớ của mình. Thay vào đó, chúng tôi đang tạo số nguyên tố tiếp theo mỗi khi chúng tôi yêu cầu.
Hãy thử nó ra:
primes = Primes(100000000000)
print(primes)
for x in primes: print(x)
---------
<__main__.Primes object at 0x1021834a8>235711...
Mỗi lần lặp lại của Primes
cuộc gọi đối tượng __next__
để tạo ra số nguyên tố tiếp theo.
Iterators chỉ có thể được lặp đi lặp lại một lần. Nếu bạn cố gắng lặp lại primes
một lần nữa, sẽ không có giá trị nào được trả lại. Nó sẽ hoạt động như một danh sách trống.
Bây giờ chúng ta đã biết trình lặp là gì và cách tạo một trình vòng lặp, chúng ta sẽ chuyển sang trình tạo.
máy phát điện
Nhớ lại rằng các hàm tạo cho phép chúng ta tạo các trình vòng lặp theo cách đơn giản hơn.
Máy phát điện giới thiệu các yield
câu lệnh cho Python. Nó hoạt động hơi giống return
bởi vì nó trả về một giá trị.
Sự khác biệt là nó tiết kiệm nhà nước của chức năng. Lần tiếp theo hàm được gọi, việc thực thi tiếp tục từ nơi nó dừng lạivới cùng giá trị biến nó đã có trước khi năng suất.
Nếu chúng ta chuyển đổi của chúng tôi Primes
iterator thành một trình tạo, nó sẽ trông như thế này:
def Primes(max): number = 1 while number < max: number += 1 if check_prime(number): yield number
primes = Primes(100000000000)
print(primes)
for x in primes: print(x)
---------
<generator object Primes at 0x10214de08>235711...
Bây giờ điều đó khá Pythonic! Chúng ta có thể làm tốt hơn không?
Đúng! chúng ta có thể sử dụng Biểu thức trình tạođược giới thiệu với PEP 289.
Đây là cách hiểu danh sách tương đương với trình tạo. Nó hoạt động chính xác giống như cách hiểu danh sách, nhưng biểu thức được bao quanh bởi ()
như trái ngược với []
.
Biểu thức sau có thể thay thế hàm tạo của chúng ta ở trên:
primes = (i for i in range(2, 100000000000) if check_prime(i))
print(primes)
for x in primes: print(x)
---------
<generator object <genexpr> at 0x101868e08>235711...
Đây là vẻ đẹp của trình tạo trong Python.
Tóm tắt…
- Trình tạo cho phép bạn tạo các trình vòng lặp theo cách rất Pythonic.
- Trình lặp cho phép đánh giá chậm, chỉ tạo phần tử tiếp theo của đối tượng có thể lặp khi được yêu cầu. Điều này rất hữu ích cho các tập dữ liệu rất lớn.
- Trình lặp và trình tạo chỉ có thể được lặp lại một lần.
- Hàm tạo tốt hơn Iterator.
- Biểu thức Trình tạo tốt hơn Trình vòng lặp (chỉ dành cho các trường hợp đơn giản).
Bạn cũng có thể xem phần giải thích của tôi về cách tôi đã sử dụng Python để tìm những người thú vị để theo dõi trên Phương tiện.
Để biết thêm thông tin cập nhật, hãy theo dõi tôi trên Twitter.