On Tue, 31 Aug 2021, 2:52 am Brett Cannon, <brett@python.org> wrote:

On Sun, Aug 29, 2021 at 2:01 PM Serhiy Storchaka <storchaka@gmail.com> wrote:

> So my question is whether the discrepancy between what `async for`
> expects and what `aiter()` expects on purpose?
> https://bugs.python.org/issue31861 <https://bugs.python.org/issue31861>
> was the issue for creating aiter() and I didn't notice a discussion of
> this difference. The key reason I'm asking is this does cause a
> deviation compared to the relationship between `for` and `iter()` (which
> does not require `__iter__` to be defined on the iterator, although
> collections.abc.Iterator does). It also makes the glossary definition
> being linked from
> https://docs.python.org/3.10/reference/compound_stmts.html#the-async-for-statement
> <https://docs.python.org/3.10/reference/compound_stmts.html#the-async-for-statement>
> incorrect.

PyIter_Check() only checks existence of __next__, not __iter__ (perhaps
for performance reasons).

Or maybe no one thought to require __iter__ for iterators?

I don't think PyIter_Check is testing the formal definition of an iterator, I think it's just testing if calling __iter__ can be skipped (as you say, for performance reasons).

I'm surprised iter() would skip calling __iter__ just because an object defines __next__, though. Even though "__iter__ is defined and returns self" is part of the iterator definition, it still feels like a leap from there to "if __next__ is defined, skip calling __iter__ in iter()".

The optimisation that bypasses the __[a]iter__ method call feels more legitimate in the actual for loop syntax, it just feels odd to me if the builtin isn't forcing the call.

Cheers,
Nick.