You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
None vs Never as typing.Generator's send type #123521
If your generator will only yield values, set the SendType and ReturnType to None
While not obviously wrong, using None as SendType looks imprecise: we want a typechecker to warn about .send(t) calls for any t, right? Using that method likely indicates that the generator is used incorrectly.
Now type checkers will reject .send(t) calls for all t types except None and Any.
Since python 3.11 we have a Never type - effectively a "please don't" type. So setting SendType to Never instead of None 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 calling it.send(None) is equivalent to calling next(it) for the next time, so None is formally correct. However, there's no benefit ever from doing it.send(None) if the generator does not use sent values - calling next(it) is clearly preferable.
My suggested solution is to recommend typing.Never as SendType in such cases in documentation. I'm ready to write a PR with this change.
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 calling it.send(None) is equivalent to calling next(it) for the next time, so None is formally correct. However, there's no benefit ever from doing it.send(None) if the generator does not use sent values - calling next(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.
Activity
ZeroIntensity commentedon Aug 30, 2024
typing.Generatoris deprecated in favor ofcollections.abc.Generator, maybe this section should be moved to over there (as well as the fix)?sterliakov commentedon Aug 30, 2024
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.
ZeroIntensity commentedon Aug 30, 2024
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.zuo commentedon Oct 3, 2024
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).
TeamSpen210 commentedon Oct 3, 2024
To 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.