-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Correct return type of sum() builtin #1582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Not sure about this; we tend to avoid union return types. |
Some context on why I'm changing this: I had code that would sum a list of mypy is in a position to know that the return value could possibly be an integer. Can you clarify why union return types are avoided? It's certainly more accurate in this case. |
One problem with union in this context is that some code may be careful to never pass an empty iterable to |
Thanks for the response. That makes sense and I imagine this change would be more painful for people being careful to never pass an empty list. But ultimately that's a dependency only on runtime data, which mypy isn't able to take into consideration. It's not really any different from a function that returns different types in the branches of an |
It's similar to Maybe One obvious improvement is to create two overloads, |
For pytype, we would write
(See e.g. the pytype definition of "reduce", https://github.com/google/pytype/blob/master/pytype/pytd/builtins/__builtin__.pytd#L92) However, neither mypy nor PEP 484 has a concept of "nothing" so this doesn't work here. |
But how would you know whether a particular variable containing a list of integers can be empty or not? Otherwise this won't be very useful -- unlike pow(), sum() is rarely called with an empty list literal -- it's called with a variable that may or may not be guaranteed to be non-empty. |
@gvanrossum I agree the overload is a definite improvement. As a starting point, here's what I believe we'd need to accurately model all behavior of @overload
def mysum(iterable: Iterable[_T]) -> Union[_T, int]: ...
@overload
def mysum(iterable: Iterable[_T], start:_S) -> Union[_T, _S]: ... In the two argument version we need a second type variable and the union because there's nothing outright requiring that the second argument be the same type as the items in the iterable, and promotion can happen either way: sum([1, 2, 3], 4.5) # float (start)
sum([1.0, 2.0, 3.5], 4) # float (iterable) Do we want to model all that behavior? I would have found it helpful for mypy to notify me of the problem with my blind |
Yes, this sounds right. We do this for e.g. dict.get() as well.
|
`sum([])` always returns the integer 0.
421e151
to
e33390b
Compare
sum([])
always returns the integer 0.