
On Mon, Nov 29, 2021, 12:16 AM Paul Bryan <pbryan@anode.ca> wrote:
And the second link?
Same comments, basically. But the more germane thing is that even assuming a class has both .__next__() and .__iter__(), it is perfectly reasonable for the latter to return something other than `self`. The Foo and Bar classes are slightly contrived, but I've written production code where e.g. `iter(thing)` returns a new `thing.__class__` instance rather than self.
On Mon, 2021-11-29 at 00:11 -0500, David Mertz, Ph.D. wrote:
On Sun, Nov 28, 2021, 11:43 PM Paul Bryan <pbryan@anode.ca> wrote:
According to https://docs.python.org/3/glossary.html#term-iterator and https://docs.python.org/3/library/stdtypes.html#typeiter, iterators must implement the __iter__ method.
From your first link:
CPython implementation detail: CPython does not consistently apply the requirement that an iterator define __iter__().
That said, I don't think the description at the link is very good. Anyway, it's different from what I teach, and also different from how Python actually behaves. E.g.:
class Foo: ... def __iter__(self): ... return Bar() ... class Bar: ... def __next__(self): ... if random() > 0.5: ... raise StopIteration ... return "Bar" ... for x in Foo(): ... print(x) ... Bar Bar Bar
Or anyway, what would you call `bar := Bar()` if not "an iterator?!
On Sun, 2021-11-28 at 22:02 -0500, David Mertz, Ph.D. wrote:
On Sun, Nov 28, 2021, 8:59 PM Steven D'Aprano
To be an iterator, your object needs:
1. a `__next__` method which returns the next value; 2. and an `__iter__` method which returns self.
That's not quite right.
An iterator only needs .__next__(), and an iterable only needs .__iter__(). Returning self is a convenient, and probably the most common, way of creating an object that is both. But exceptions exist, and remain iterators and/or iterables.