-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Mypy can't infer parameter types for nested function calls. #8666
Comments
I'm also experiencing a similar issue. py.py:7: error: Value of type "Iterable[Any]" is not indexable from functools import reduce
from typing import List
def _parseShortFlags(flags: List[str]):
# Reduce the list of strings to a set with each unique character
options: set = set(reduce(lambda a, b: a[1:] + b[1:], flags))
print(sorted(options)) # Shows ['a', 'l', 'o']
_parseShortFlags(['-la', '-ll', '-oa']) I guess |
When replacing py.py:7: error: Value of type "Iterable[str]" is not indexable |
And this gives no errors from functools import reduce
from typing import List
def _parseShortFlags(flags: List[str]):
# Reduce the list of strings to a string with each character
options: str = reduce(lambda a, b: a[1:] + b[1:], flags)
print(options)
_parseShortFlags(['-la', '-ll', '-oa']) So mypy already knows that str[1:] + str[1:] -> str is always true. |
@marcospb19 Yes, I can say it's the same issue. With your code since using the set constructor dictates that it's taking an iterable(Iterable[Any], or Iterable[str] with Set[str]), it's inferring that the return value type of reduce is also an iterable. The first argument to reduce is a callable taking two values of the same type as that of reduce return value, here iterable, and producing a value of the same type, iterable. This means that both a and b are now considered to be iterables, and of course it isn't possible to just concatenate iterables with the addition operator +. Your code can be altered in the same way as mine to get it to work. I did a try here https://mypy-play.net/?mypy=latest&python=3.8&gist=2ac5ba0daf467cbfaf3655f704e95ac4 and it worked fine. There can be other workarounds of course like treating a and b as really Iterable[str] and using chain and islice from itertools to accomplish the same goal you're seeking. That's very far from an elegant way though, I would say. |
I'm trying to run mypy against this code
I get the following error message:
It seems like mypy is starting type inference from the outside and inward, so it starts with itertools.starmap. The first callable is considered to take arguments resulting from the unpacking of an iterable: Iterable[Any], hence the second argument is considered Iterable[Iterable[Any]]. Since the second argument to itertools.starmap here is a function call to filter, it's assumed that filter must return Iterable[Iterable[Any]] to match the second argument expected by itertools.starmap. This coerces the second argument to filter to be seen as Iterable[Iterable[Any]], which in turn coerces the first argument to filter to be seen as a callable taking Iteable[Any]. This overlooks the explicitly obvious fact here that the second argument to filter is actually List[Tuple[int, int]](or at worst Iterable[Tuple[int, int]]) which will cause the first filter argument to be a callable that takes Tuple[int, int], effectively suppressing the spurious error.
One way to overcome this misinterpretation of the argument types is to explicitly cast the result of filter to be Iterable[Tuple[int, int]], which will rightfully suppress the error.
mypy version: 0.761
python version: 3.7.6
The text was updated successfully, but these errors were encountered: