Các câu trả lời trên rất hay, nhưng như hầu hết những gì tôi đã thấy, đừng nhấn mạnh sự khác biệt đủ cho những người như tôi.
Ngoài ra, mọi người có xu hướng nhận được "quá Pythonic" bằng cách đặt các định nghĩa như "X là một đối tượng có __foo__()
phương thức" trước đó. Các định nghĩa như vậy là chính xác - chúng dựa trên triết lý gõ vịt, nhưng trọng tâm của các phương pháp có xu hướng giữa khi cố gắng hiểu khái niệm này trong sự đơn giản của nó.
Vì vậy, tôi thêm phiên bản của tôi.
Trong ngôn ngữ tự nhiên,
- lặp là quá trình lấy một phần tử tại một thời điểm trong một hàng các phần tử.
Trong Python
iterable là một đối tượng, tốt, lặp đi lặp lại, đơn giản chỉ có nghĩa là nó có thể được sử dụng trong phép lặp, ví dụ như với một for
vòng lặp. Làm sao? Bằng cách sử dụng iterator . Tôi sẽ giải thích bên dưới.
... trong khi iterator là một đối tượng xác định cách thực sự lặp lại - cụ thể là phần tử tiếp theo là gì . Đó là lý do tại sao nó phải có
next()
phương pháp.
Các trình lặp cũng tự lặp lại, với sự khác biệt là __iter__()
phương thức của chúng trả về cùng một đối tượng ( self
), bất kể các mục của nó có được sử dụng bởi các lệnh gọi trước hay không next()
.
Vậy trình thông dịch Python nghĩ gì khi thấy for x in obj:
câu lệnh?
Hãy nhìn xem, một for
vòng lặp. Trông giống như một công việc cho một trình vòng lặp ... Hãy lấy một cái. ... Có obj
anh chàng này , vì vậy hãy hỏi anh ta.
"Ông obj
, bạn có lặp lại không?" (... các cuộc gọi iter(obj)
, cuộc gọi này
obj.__iter__()
, vui vẻ đưa ra một trình vòng lặp mới sáng bóng _i
.)
OK, thật dễ dàng ... Hãy bắt đầu lặp đi lặp lại. ( x = _i.next()
... x = _i.next()
...)
Vì Mr. obj
đã thành công trong bài kiểm tra này (bằng cách có một phương thức nhất định trả về một trình vòng lặp hợp lệ), chúng tôi thưởng cho anh ấy bằng tính từ: bây giờ bạn có thể gọi anh ấy là "ông lặp đi lặp lại obj
".
Tuy nhiên, trong các trường hợp đơn giản, thông thường bạn không được hưởng lợi từ việc có trình vòng lặp và vòng lặp riêng biệt. Vì vậy, bạn chỉ xác định một đối tượng, đó cũng là trình lặp riêng của nó. (Python không thực sự quan tâm đến việc được _i
đưa ra bởi obj
không phải là tất cả sáng bóng, mà chỉ là obj
chính nó.)
Đây là lý do tại sao trong hầu hết các ví dụ tôi đã thấy (và những gì đã làm tôi bối rối nhiều lần), bạn có thể thấy:
class IterableExample(object):
def __iter__(self):
return self
def next(self):
pass
thay vì
class Iterator(object):
def next(self):
pass
class Iterable(object):
def __iter__(self):
return Iterator()
Tuy nhiên, có những trường hợp khi bạn có thể hưởng lợi từ việc iterator tách khỏi iterable, chẳng hạn như khi bạn muốn có một hàng vật phẩm, nhưng nhiều "con trỏ" hơn. Ví dụ: khi bạn muốn làm việc với các phần tử "hiện tại" và "sắp tới", bạn có thể có các trình vòng lặp riêng cho cả hai. Hoặc nhiều luồng kéo từ một danh sách lớn: mỗi luồng có thể có trình vòng lặp riêng để duyệt qua tất cả các mục. Xem câu trả lời của @ Raymond và @ glglgl ở trên.
Hãy tưởng tượng những gì bạn có thể làm:
class SmartIterableExample(object):
def create_iterator(self):
# An amazingly powerful yet simple way to create arbitrary
# iterator, utilizing object state (or not, if you are fan
# of functional), magic and nuclear waste--no kittens hurt.
pass # don't forget to add the next() method
def __iter__(self):
return self.create_iterator()
Ghi chú:
Tôi sẽ nhắc lại lần nữa: iterator không lặp lại được . Iterator không thể được sử dụng như một "nguồn" trong for
vòng lặp. Những gì for
vòng lặp chủ yếu cần là __iter__()
(mà trả lại một cái gì đó với next()
).
Tất nhiên, for
không phải là vòng lặp duy nhất, vì vậy, ở trên cũng áp dụng cho một số cấu trúc khác ( while
...).
Iterator next()
có thể ném StopIteration để dừng lặp. Mặc dù vậy, nó không phải lặp đi lặp lại hoặc sử dụng các phương tiện khác.
Trong "quá trình suy nghĩ" ở trên, _i
không thực sự tồn tại. Tôi đã tạo nên cái tên đó.
next()
Bây giờ phải có một thay đổi nhỏ trong phương thức Python 3.x: (không phải là tích hợp sẵn) __next__()
. Vâng, nó đáng lẽ phải như thế suốt.
Bạn cũng có thể nghĩ về nó như thế này: iterable có dữ liệu, iterator kéo mục tiếp theo
Tuyên bố miễn trừ trách nhiệm: Tôi không phải là nhà phát triển của bất kỳ trình thông dịch Python nào, vì vậy tôi không thực sự biết trình thông dịch "nghĩ gì". Những suy ngẫm ở trên chỉ là minh chứng cho cách tôi hiểu chủ đề từ những giải thích, thí nghiệm và trải nghiệm thực tế khác của một người mới chơi Python.
collections.abc.AsyncIterator
các bài kiểm tra__aiter__
và__anext__
phương pháp. Đây là một bổ sung mới trong 3.6.