Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Generator trong Python
Trong bài này chúng ta sẽ tìm hiểu về Generator trong Python, đây là cách giúp bạn tạo ra một đối tượng iterator cực kì dễ dàng. Bên cạn đó mình cũng phân tích giúp bạn hiểu được sự khác nhau giữa một hàm bình thường và một hàm generator.

1. Generators trong Python là gì?
Generator là cách tạo ra một mô hình lặp iterator trong Python, bằng cách sử dụng từ khóa yield để tạo ra những trình lặp một cách đơn giản và hiệu quả nhất.
Một hàm khi sử dụng yield thì bản thân nó đã tự kế thừa hai phương thức __iter__() và __next__() nên ta có thể sử dụng hàm next() mà không cần phải sử dụng hàm iter() để khởi tạo iterator.
2. Cách tạo Generators trong Python
Việc tạo một generator trong Python khá là đơn giản, nó giống như một hàm bình thường, nhưng thay vì sử dụng lệnh return để trả về thì ta sử dụng lệnh yield.
Bài viết này được đăng tại [free tuts .net]
Nếu một function (hàm) có chứa một hoặc nhiều lệnh yield thì nó là một generator. Một hàm có thể có một hoặc nhiều lệnh yield đặt tại nhiều vị trí khác nhau trong hàm.
Sự khác nhau giữa lệnh return và yield là trong khi return sẽ trả về một giá trị và kết thúc hàm, nhưng yield thì sẽ trả về nhưng vẫn giữ lại trạng thái của các biến, sau đó nếu được gọi tiếp thì nó sẽ tiếp tục xử lý ngay tại vị trí tạm dừng đó.
3. Sự khác nhau giữa hàm generator và hàm bình thường
Dưới đây là một vài điểm khác nhau giữa hàm generator và hàm bình thường.
- Generator chứa một hoặc nhiều lệnh yield.
- Khi được gọi, hàm generator sẽ trả về một đối tượng iterator nhưng nó không thực thi liền.
- Hai phương thức
__iter__()và__next__()được kế thừa tự động, vì vậy bạn có thể sử dụng hàmnext()mà không cần dùng hàmiter()để tạo iterator . - Trạng thái của các biến được lưu trữ lại giữa những lần gọi.
- Cuối cùng khi hàm kết thúc thì
StopIterationsẽ bung ra cho lần gọi hàm tiếp theo, đây là lỗi cho thấy iterator đã duyệt đến phần tử cuối cùng.
Hãy xem ví dụ dưới đây để hiểu rõ hơn.
# HỌC PYTHON TAI FREETUTS.NET
# AUTHOR: CƯỜNG NGUYỄN
def generateNumber():
n = 1
print("Lần gọi thứ nhất trả về n = ", n)
yield n
n += 1
print("Lần gọi thứ hai trả về n = ", n)
yield n
n += 1
print("Lần gọi thứ ba trả về n = ", n)
yield n
# Chương trình chính
num = generateNumber()
# Kiểm tra xe num là gì?
# => Nó là một generate object
# <generator object generateNumber at 0x000001CD0A939510>
print(num)
# Gọi đến generate => trả về yield đầu tiên
# Kết quả: 1
print(next(num))
# Gọi đến generate => trả về yield thứ hai
# Kết quả: 2
print(next(num))
# Gọi đến generate => trả về yield thứ ba
# Kết quả: 3
print(next(num))Như bạn thấy, biến n bên trong hàm đã được nhớ sau mỗi lần gọi.
4. Sử dụng vòng lặp trong Generator Python
Ở ví dụ trên mình chỉ giải thích cách hoạt động của generator chứ thực tế không ai làm như vậy.
Chúng ta thường sử dụng vòng lặp để tạo ra những generator.
Hãy xem ví dụ dưới đây, mình sẽ tạo ra một generator các số từ 1 đến 10.
# Tạo generator
def generateNumber():
for i in range(1, 11):
yield i
# Lặp qua generator
num = generateNumber()
for n in num:
print(n)Kết quả như sau:
5. Sử dụng generator expression trong Python
Ngoài những cách trên thì bạn có thể tạo ra generator bằng biểu thức expression.
Cách hoạt động của nó giống như list comprehension, chỉ có điều một bên sử dụng dấu ngoặc vuông, một bên sử dụng dấu ngoặc nhọn.
Cách này chỉ phù hợp với những trường hợp có list data sẵn, và bạn muốn tạo ra một generator dựa trên list đó.
# Tạo list
my_list = [1, 3, 6, 10]
# Sử dụng expression để tạo generator
generator = (x**2 for x in my_list)
for item in generator:
print(item)Kết quả:
Ta có thể viết lại ví dụ trên bằng cách sử dụng vòng lặp như sau:
# Tạo list
my_list = [1, 3, 6, 10]
# Sử dụng vòng lặp
def newList(my_list):
for item in my_list:
yield item
generator = newList(my_list)
for item in generator:
print(item)6. Tại sao nên dùng generator trong Python?
Lý do đơn giản và thuyết phục nhất là generator rất đơn giản và dễ thực hiện.
Generator triển khai dễ dàng và ngắn gọn hơn nhiều so với việc sử dụng trình lặp của iterator.
Ví dụ: Xây dựng một iterator tính lũy thừa của 2.
class LuyThua2():
def __init__(self, max = 0):
# Thuộc tính lưu số lũy thừa hiện tại
self.n = 0
# Thuộc tính lưu số lũy thừa tối đa
self.max = max
def __iter__(self):
return self
def __next__(self):
if self.n > self.max:
raise StopIteration
else:
result = 2 ** self.n
self.n += 1
return result
l = LuyThua2(5)
print(next(l)) # n = 0
print(next(l)) # n = 1
print(next(l)) # n = 2
print(next(l)) # n = 3
print(next(l)) # n = 4
print(next(l)) # n = 5
print(next(l)) # Trả về lỗi StopIterationNhưng nếu viết bằng Generator thì chương trình rất ngắn gọn như sau:
def LuyThua2(max = 0):
n = 0
while n <= max:
yield 2 ** n
n += 1
l = LuyThua2(5)
print(next(l)) # n = 1
print(next(l)) # n = 2
print(next(l)) # n = 3
print(next(l)) # n = 4
print(next(l)) # n = 5
print(next(l)) # n = 6
print(next(l)) # Lỗi StopIterationNgoài ra, generator thân thiện hơn bởi nó chỉ tạo ra một mục tại một thời điểm gọi.
Trên là những chia sẻ cơ bản về cách sử dụng generator trong Python.

Các kiểu dữ liệu trong C ( int - float - double - char ...)
Thuật toán tìm ước chung lớn nhất trong C/C++
Cấu trúc lệnh switch case trong C++ (có bài tập thực hành)
ComboBox - ListBox trong lập trình C# winforms
Random trong Python: Tạo số random ngẫu nhiên
Lệnh cin và cout trong C++
Cách khai báo biến trong PHP, các loại biến thường gặp
Download và cài đặt Vertrigo Server
Thẻ li trong HTML
Thẻ article trong HTML5
Cấu trúc HTML5: Cách tạo template HTML5 đầu tiên
Cách dùng thẻ img trong HTML và các thuộc tính của img
Thẻ a trong HTML và các thuộc tính của thẻ a thường dùng