On Wed, Sep 15, 2021 at 04:01:31PM -0700, Guido van Rossum wrote:

> Steven's class A is the kind of class a custom sequence might return from
> its __iter__ method. E.g.
> 
> class S:
>     def __iter__(self):
>         return A()

Correct, where A itself has a `__next__` method but no `__iter__` 
method.

 
> Now this works:
> 
> for x in S(): ...

Agreed.


> However this doesn't:
> 
> for x in iter(S()): ...

Correct, but *in practice* nobody would actually write it like that, 
since that would be silly. But what can happen is that one might have 
earlier called iter() directly, and only afterwards used the result in a 
for loop.

    it = iter(S())
    # assert isinstance(it, A)
    ...
    for x in it: ...

Or we can short-cut the discussion and just write it like this:

    for x in A():  ...

which clearly fails because A has no `__iter__` method. When we write it 
like that, it is clear that A is not an iterator. The waters are only 
muddied because *most of the time* we don't write it like that, we do 
the simplest thing that can work:

    for x in S(): ...

which does work.

So the question is, in that last snippet, the version that *does* work, 
what are we iterating over? Are we iterating over S() or A()?

I think the answer is Yes :-)


> In Steven's view, A does not deserve to work in the former case: Because A
> is a "broken" iterator, he seems to want it rejected by the iter() call
> that is *implicit* in the for-loop.

No, I'm not arguing that.

1. It's not a matter of "deserves", it is that A instances cannot be 
used *directly* in a for loop, because they have no `__iter__` method.

2. I don't want iter() or the for loop to reject *S* instances just 
because A instances don't have `__iter__`.

3. I don't need to propose that for loops reject A instances, since 
they already do that. That's the status quo, and it's working correctly 
according to the iterator protocol.

The bottom line here is that I'm not asking for any runtime changes here 
at all. Perhaps improving the docs would be a good thing, and honestly 
I'm unsure what typeshed should do. I suppose that depends on whether 
you see the role of static type checking to be as strict as possible or 
as forgiving as possible.

If you want your type checking to be strict, then maybe you want it to 
flag A as not an iterator. If you want it to accept anything that works, 
maybe you want it to allow S as an iterator.

On the typeshed issue, Akuli comments that they have a policy of 
preferring false negatives. So I think that nothing needs to be done?

https://github.com/python/typeshed/issues/6030#issuecomment-918544344



-- 
Steve
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/3BQ2KIYFVRDKRK3HFLAFPS2GCBEAT24R/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to