Repository navigation
None vs Never as typing.Generator's send type #123521
Description
Activity
typing.Generatoris deprecated in favor ofcollections.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,CoroutineandAsyncGeneratoralso have typing-related descriptions there that aren't present in correspondingcollections.abcdocumentation 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
Noneis there to match runtime behaviour closer since callingit.send(None)is equivalent to callingnext(it)for the next time, soNoneis 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, butit.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).
Reacted by Jelle ZijlstraTo me, it makes sense to change
send()to acceptSendType | None) - regardless of whatSendTypeis,Noneis an acceptable call. Then usingSendType = Neverwould be correct, the union simplifies to justNone. Preventingsend(None)isn't really too useful, since the caller could just as easily donext(), causing the same unsafety. The problem really is that regardless of the defined send type, generators always needNonesent 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.Generatorcurrently says:While not obviously wrong, using
NoneasSendTypelooks 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 allttypes exceptNoneandAny.Since python 3.11 we have a
Nevertype - effectively a "please don't" type. So settingSendTypetoNeverinstead ofNonewould be more useful from the interface declaration perspective: literally saying "please don't send anything here".I do understand that
Noneis there to match runtime behaviour closer since callingit.send(None)is equivalent to callingnext(it)for the next time, soNoneis 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.NeverasSendTypein such cases in documentation. I'm ready to write a PR with this change.