Iterables và Iterators thường bị nhầm lẫn với nhau, tuy nhiên, chúng là hai khái niệm khác biệt. Bài viết này sẽ giải thích sự khác biệt giữa hai loại này và cách chúng được sử dụng. Đầu tiên chúng ta hãy xem xét ngắn gọn Iteration là gì
Theo thuật ngữ của giáo dân, Lặp lại có nghĩa là 'các bước lặp lại'. Trong thuật ngữ lập trình, Lặp lại là sự lặp lại của một câu lệnh/khối mã một số lần cụ thể, tạo ra đầu ra lần lượt. Các phép lặp có thể được thực hiện bằng cách sử dụng các vòng lặp for chẳng hạn.
Iterables trong Python
Iterables là các đối tượng có thể được lặp/lặp đi lặp lại bằng cách sử dụng vòng lặp for. Iterables chứa dữ liệu hoặc có giá trị, trong đó việc thực thi vòng lặp for sẽ thực hiện một phép lặp, tạo ra kết quả lần lượt.
Một iterable thực hiện phương thức __iter__() và trả về một đối tượng iterator. Tuy nhiên, nếu phương thức __iter__() không được định nghĩa, Python sẽ sử dụng ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']0 để thay thế.
Ví dụ về Iterables là danh sách, từ điển, chuỗi, bộ dữ liệu, v.v. Miễn là bạn có thể lặp lại nó, nó là một Iterable.
Để tìm hiểu xem một đối tượng có thể lặp lại hay không, bạn sẽ phải kiểm tra xem nó có hỗ trợ ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']1. Để làm điều này, chúng tôi sử dụng hàm ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']2, trả về tất cả các thuộc tính và phương thức của đối tượng được chỉ định, ngoại trừ các giá trị.
Mã ví dụ
class Person: name = "Nisha" age = 25 country = "England" print(dir(Person))
đầu ra
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']
Trình lặp trong Python
Một Iterator cũng là một đối tượng sử dụng các phương thức __iter__() và ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'age', 'country', 'name']4, đây được gọi là giao thức Iterator. Nó là một đối tượng có thể lặp lại với một trạng thái, nghĩa là nó ghi nhớ nó đang ở giai đoạn nào trong quá trình lặp lại.
Iterator trả về giá trị, mỗi lần một phần tử. Khi giá trị tiếp theo của đối tượng Iterable được trả về, trạng thái của trình vòng lặp được cập nhật và biết cách lấy giá trị tiếp theo bằng phương thức ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']4. Iterators chỉ có thể di chuyển về phía trước, chúng không thể quay lại hoặc tự đặt lại.
Các trình vòng lặp cũng đưa ra một ngoại lệ StopIteration khi không còn phần tử nào nữa hoặc đối tượng đã cạn kiệt.
Mã ví dụ
Ở đây tôi đã tạo một trình vòng lặp có tên là 'số'. Tôi đã đặt một dòng mã để kiểm tra loại của nó. Chúng tôi đang mong đợi phép lặp sẽ xuất ra tất cả các số. Tuy nhiên, tôi đã yêu cầu nó in đầu ra thứ 6, mặc dù chỉ có 5 giá trị trong iterator. Hãy xem điều gì sẽ xảy ra
numbers = iter([2, 4, 6, 8, 10]) print(type(numbers)) print(next(numbers)) print(next(numbers)) print(next(numbers)) print(next(numbers)) print(next(numbers)) # The next() function will raise StopIteration as it is exhausted print(next(numbers))
đầu ra
Chúng ta có thể thấy rằng loại là một 'list_iterator'. Đầu ra dừng ở 10 và tăng lên một ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']6 vì không còn phần tử nào trong danh sách số.
<class 'list_iterator'> 2 4 6 8 10 --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-15-0cb721c5f355> in <module>() 11 12 # The bext() function will raise StopIteration as it is exhausted ---> 13 print(next(numbers)) StopIteration:
Hạn chế của Iterator
- Trình vòng lặp chỉ di chuyển theo hướng thuận, chúng không quay ngược hoặc đặt lại
- Không thể sao chép các trình vòng lặp vì nó là đối tượng một chiều chỉ có thể di chuyển về phía trước
- Do hướng một chiều, không có cách nào để truy xuất phần tử trước đó.
Điểm tương đồng và khác biệt giữa Iterables và Iterators
IterableIterator Lặp lại bằng cách sử dụng. vòng lặp for vòng lặp for Phương pháp được sử dụng. __iter__() __iter__() và __next__()
Iterator là một Iterable, vì nó cũng triển khai phương thức __iter__().
Nhớ. Mọi Iterator đều là Iterable, tuy nhiên không phải Iterable nào cũng là Iterator.
Ví dụ về ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'age', 'country', 'name']2 của một Iterable
numbers = [2, 4, 6, 8, 10] print(dir(numbers))
đầu ra
Trong kết quả này, tôi đã đánh dấu ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']1, cho thấy rằng đó là một phương thức của Iterable
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Ví dụ về ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'age', 'country', 'name']2 của một Iterator
Trong ví dụ này, chúng tôi đang lặp lại danh sách số.
numbers = [2, 4, 6, 8, 10] numbers2 = iter(numbers) print(dir(numbers2))
đầu ra
Trong kết quả này, tôi đã đánh dấu ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'country', 'name']1 và numbers = iter([2, 4, 6, 8, 10]) print(type(numbers)) print(next(numbers)) print(next(numbers)) print(next(numbers)) print(next(numbers)) print(next(numbers)) # The next() function will raise StopIteration as it is exhausted print(next(numbers))2, cho thấy rằng đó là một phương thức của Iterator
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
Tôi hy vọng blog ngắn này đã giúp bạn hiểu rõ hơn về sự khác biệt giữa Iterable và Iterator