Đối tượng Iterator trong Python – sentayho.com.vn

Iterator là các đối tượng cho phép ta lấy từng phần tử của nó, hành động này có thể được lặp đi lặp lại. Trong bài viết này, Quantrimang sẽ cùng bạn sẽ tìm hiểu cách iterator hoạt động trong Python và cách bạn có thể xây dựng trình lặp của riêng mình bằng các phương thức __iter__ và __next__.



Iterator trong Python là gì?

Iterator ở khắp mọi nơi trong Python, bên trong các vòng lặp, comprehension, generator…

Nó đơn giản chỉ là các đối tượng cho phép ta lấy từng phần tử, bất cứ khi nào bạn sử dụng vòng lặp hay các kĩ thuật để có được giá trị một nhóm phần tử ở một thời điểm nào đó.

Về mặt kỹ thuật, Iterator trong Python phải thực hiện hai phương thức đặc biệt là __iter__() và __next__(), gọi chung là giao thức iterator (Iterator Protocol)

  • Phương thức __iter__ trả về chính đối tượng iterator. Phương thức này được yêu cầu cài đặt cho cả đối tượng “iterable” và iterator để có thể sử dụng các câu lệnh for và in.
  • Phương thức __next__ trả về phần tử tiếp theo. Nếu không còn phần tử nào nữa thì sẽ có lỗi StopIteration xảy ra.

Đối tượng Iterator trong Python - sentayho.com.vn

Iterable object là một đối tượng sau khi sử dụng các phương thức sẽ trả về một iterator, ví dụ như Chuỗi, List, Tuple.

Iter() là một hàm dựng sẵn trong Python nhận đầu vào là một đối tượng iterable và trả về kết quả là một iterator.

# Khai bao mot listmy_list = [4, 7, 0, 3] # lay mot iterator bang cach su dung iter()my_iter = iter(my_list) ## su dung next() #prints 4print(next(my_iter)) #prints 7print(next(my_iter)) ## next(obj) chinh la obj.__next__() #prints 0print(my_iter.__next__()) #prints 3print(my_iter.__next__()) ## Xay ra loi StopIteration vi het gia tri tra venext(my_iter)

Chạy chương trình, kết quả trả về là:

4703 Traceback (most recent call last):File “<stdin>”, line 24, in <module>next(my_iter)StopIteration

Một cách tương tự trả về kết quả này là ta sử dụng vòng lặp for.

>>> for element in my_list:… print(element)…4703

Cách vòng lặp hoạt động

Như chúng ta thấy trong ví dụ trên, vòng lặp for có thể lặp lại tự động thông qua việc sử dụng danh sách.

Trong thực tế, vòng lặp for có thể lặp lại trên bất kỳ iterable nào. Chúng ta hãy xem kỹ hơn về cách vòng lặp for được thực hiện trong Python.

for element in iterable:# do something with element

Được thực hiện tương tự như:

# iter_obj là một iterator object tạo từ iterableiter_obj = iter(iterable) # vòng lặpwhile True: try: # sử dụng next element = next(iter_obj) except StopIteration: # nếu xảy ra lỗi StopIteration thì vòng lặp sẽ được break ra ngoài break

Ở ví dụ này, bên trong vòng lặp for ta tạo một iterator object tên là iter_obj bằng cách gọi iter() trên iterable.

Và như bạn thấy thì vòng lặp for ở đây chính là vòng lặp while vô hạn. Next() bên trong vòng lặp lấy ra các phần tử để thực hiện các câu lệnh ở for loop. Đến khi lấy hết các giá trị thì ngoại lệ StopIteration sẽ được sinh ra và vòng lặp kết thúc.

Xây dựng trình vòng lặp Iterator trong Python

Chúng ta có thể tự xây dựng iterator là một class. Xây dựng Iterator rất dễ dàng trong Python, chúng ta chỉ cần thực hiện các phương thức __iter__() và __next__().

class PowTwo: def __init__(self, max = 0): sentayho.com.vn = max def __iter__(self): self.n = 0 return self def __next__(self): if self.n <= sentayho.com.vn: result = 2 ** self.n self.n += 1 return result else:raise StopIteration

Phương thức __iter__ sẽ làm đối tượng trở thành đối tượng iterable.

Giá trị trả về của __iter__ là một iterator. Nó cần có phương thức __next__ và trả về StopIteration nếu không còn phần thử nào nữa.

Tạo ra một iterator và chạy chương trình như sau:

>>> a = PowTwo(4)>>> i = iter(a)>>> next(i)1>>> next(i)2>>> next(i)4>>> next(i)8>>> next(i)16>>> next(i)Traceback (most recent call last):…StopIteration

Chúng ta cũng có thể sử dụng một vòng lặp for để lặp iterator

>>> for i in PowTwo(5):… print(i)…12481632

Iterator lặp vô hạn trong Python

Không phải tất cả các đối tượng iterator đều sẽ được gọi hết các phần tử và kết thúc khi không còn phần tử. Có một số trường hợp iterator sẽ lặp vô hạn. Ví dụ như sau:

>>> int()0>>> inf = iter(int,1)>>> next(inf)0>>> next(inf)0

Chúng ta có thể thấy rằng hàm int() luôn trả về 0. Vì vậy, việc truyền nó dưới dạng iter(int, 1) sẽ trả về một iterator lặp cho đến khi giá trị trả về bằng 1. Điều này không bao giờ xảy ra và đây chính là iterator lặp vô hạn. Bạn cần chú ý khi xử lý trong các trường hợp thế này.

Ngoài ra, bạn cũng có thể tự xây dựng iterator lặp vô hạn. Ví dụ sau đây sẽ lặp vô hạn và trả về các số lẻ vì không có điều kiện dừng nào cả.

class InfIter: def __iter__(self): sentayho.com.vn = 1 return self def __next__(self): num = sentayho.com.vn sentayho.com.vn += 2 return num

Chạy chương trình:

>>> a = iter(InfIter())>>> next(a)1>>> next(a)3>>> next(a)5>>> next(a)7

Ưu điểm của việc sử dụng Iterator lặp là chúng tiết kiệm tài nguyên. Giống như hiển thị ở trên, bạn có thể nhận được tất cả các số lẻ mà không lưu trữ trên toàn bộ hệ thống số ở bộ nhớ.

Xem thêm:

  • Lập trình hướng đối tượng trong Python
  • Kế thừa (Inheritance) trong Python
  • Các kỹ thuật vòng lặp trong Python

Bài trước: Nạp chồng toán tử trong Python

Bài tiếp: Generator trong Python