Open sterliakov opened 2 months ago
typing.Generator
is deprecated in favor of collections.abc.Generator
, maybe this section should be moved to over there (as well as the fix)?
Hm, it's an interesting question that needs a separate ticket, IMO. I'll create and link it here.
Your observation applies to other such generics - Callable
, Coroutine
and AsyncGenerator
also have typing-related descriptions there that aren't present in corresponding collections.abc
documentation entries.
I'm also not sure whether it should be moved or duplicated there - obviously moving is saner, but harms searching significantly.
IMO, if we want to people to migrate to collections.abc
, having the only examples available on the typing page is probably a bad idea. I think we should move them.
I do understand that
None
is there to match runtime behaviour closer since callingit.send(None)
is equivalent to callingnext(it)
for the next time, soNone
is formally correct. However, there's no benefit ever from doingit.send(None)
if the generator does not use sent values - callingnext(it)
is clearly preferable.
Typically, next(it)
is preferable for such a generator, but it.send(None)
is still perfectly valid, and in some cases it may be more convenient, e.g., just to treat various kinds of generators uniformly in some code...
I'd say that the generator's interface should not try to know better the context in which it may be used. That's the competence of the client code (the code which makes use of that interface).
To me, it makes sense to change send()
to accept SendType | None
) - regardless of what SendType
is, None
is an acceptable call. Then using SendType = Never
would be correct, the union simplifies to just None
. Preventing send(None)
isn't really too useful, since the caller could just as easily do next()
, causing the same unsafety. The problem really is that regardless of the defined send type, generators always need None
sent the first time, but only then.
If you do want to protect against that, you'd really need some sort of wrapper - maybe a function which calls the generator, advances once, then returns it casted to a protocol that disallows iteration/next.
Documentation
Documentation for
typing.Generator
currently says:While not obviously wrong, using
None
asSendType
looks imprecise: we want a typechecker to warn about.send(t)
calls for anyt
, right? Using that method likely indicates that the generator is used incorrectly.Now type checkers will reject
.send(t)
calls for allt
types exceptNone
andAny
.Since python 3.11 we have a
Never
type - effectively a "please don't" type. So settingSendType
toNever
instead ofNone
would be more useful from the interface declaration perspective: literally saying "please don't send anything here".I do understand that
None
is there to match runtime behaviour closer since callingit.send(None)
is equivalent to callingnext(it)
for the next time, soNone
is formally correct. However, there's no benefit ever from doingit.send(None)
if the generator does not use sent values - callingnext(it)
is clearly preferable.My suggested solution is to recommend
typing.Never
asSendType
in such cases in documentation. I'm ready to write a PR with this change.