-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Allow yielding result of function that returns None #1933
Comments
To clarify: I do not think that My thoughts on My thoughts on |
I haven't thought about this very carefully, but I'd rather generate errors on questionable code even if doesn't fail at runtime, as in this case the rejected code seems pointless and it's likely almost always an error. Some specifics below. About About About About being able to use |
Currently, the error for We can keep this issue open as a reminder to improve the error messages. I |
Here is an update on the issue: def f() -> None:
pass
def g() -> Iterator:
yield from 1 # "yield from" can't be applied to "int", which is a good error message
x = f() # "f" does not return a value, which is a reasonable error
yield f() # "f" does not return a value, which is a false positive, since we may just want to give control to "f" I am updating labels and title accordingly. |
I don't think the error on |
I think both are legitimate statements, def g():
...
f()
yield None also this error is confusing in case of |
If a generator returns None, the StopIteration.args tuple is empty. The fact we explicitly checks for it and in that case we return none looks now an error for Mypy. I don't see an obvious way around it. Maybe related to python/mypy#1933 which is an historical issue (opened in 2016). Reported in python/mypy#18073
If a generator returns None, the StopIteration.args tuple is empty. The fact we explicitly checks for it and in that case we return none looks now an error for Mypy. I don't see an obvious way around it. Maybe related to python/mypy#1933 which is an historical issue (opened in 2016). Reported in python/mypy#18073
UPDATE: see below for current status #1933 (comment)
This is a spin-off from PR #1808. @ddfisher and I cannot agree on what the default type should be in the three methods
get_generator_yield_type()
,get_generator_receive_type()
,get_generator_return_type()
.The setting: when the user defines a generator function, they can specify a return type. The return type is required to be a supertype of
Generator
; this constrains it toIterator
,Iterable
,object
(andAny
, which is special in other ways).The
Generator
type has three type parameters:ty
, the yield type: the type ofy
inyield y
tc
, the receive type: the type ofc
inc = yield ...
tr
, the return type: the type ofr
inreturn r
Note that
tr
is fairly new -- it was introduced in Python 3.3 by PEP 380 for the benefit ofyield from
.tc
is older, it dates back to Python 2.5 and PEP 342 (it is the value sent to the generator using the.send()
method).ty
is the oldest; whenyield
was originally introduced in Python 2.2 by PEP 255, it was a statement. Before PEP 380,return
in a generator function was not allowed to return a value.When a generator function is just intended to be used as an iterator, there's no need to specify
tc
andtr
, and the recommended type isIterator[ty]
. (Iterable[ty]
is also allowed and means roughly the same thing.) In this case the user of the iterator has no access to the.send()
method. Hence,yield
might as well be considered a statement, since it's never going to return anything other thanNone
. Likewise, there's no point is returning a value with areturn
statement since the user of the iterator in all likelihood is just going to iterate over it until it raisesStopIteration
(since that's all that regular iterators do).This is where @ddfisher and I disagree -- I find it useful if the defaults for
tc
andtr
are None (or perhaps Void), so that mypy will flag an error in the generator body if you either try to useyield ...
as an expression, or try to return a value usingreturn <expr>
. David (IIUC) believes that both should beAny
, giving the reason that "it should be allow to pointless but harmless things." (The code currently hastc
default toVoid
andtr
default toAny
. Go figure.)My problem with David's position is that I want mypy to be strict about pointless things that are likely the result of either a misunderstanding or a refactoring gone bad. I have seen enough people make the mistake of accidentally writing
return v
instead ofyield v
in a generator that I want this to be flagged as an error. There's also the somewhat analogous case of a regular function declared to returnNone
-- it would be pointless but harmless to return some value here, so maybe David believes that we shouldn't flag that as an error either?I'm not sure why the existing code (written by David) has
Void
as the default fortc
, but I think it may be because this parameter ofGenerator
is contravariant. So hopefully we at least agree here. :-)David, please feel free to explain your position more fully (I think you were calling on the formal type system but we ran out of time in our in-person discussion at that point).
The text was updated successfully, but these errors were encountered: