'How to type a function attribute in NamedTuple
I have a piece of code like
from typing import Callable, NamedTuple, TypeVar
def f1(x: int) -> int:
return x
def f2(y: str) -> int:
return len(y)
T = TypeVar("T", int, str)
class Config(NamedTuple):
func: Callable[[T], int]
c1 = Config(func=f1)
c2 = Config(func=f2)
Mypy complains:
toy.py:19:18: error: Argument "func" to "Config" has incompatible type "Callable[[int], int]"; expected "Callable[[Config], int]"
toy.py:20:18: error: Argument "func" to "Config" has incompatible type "Callable[[str], int]"; expected "Callable[[Config], int]"
Found 2 errors in 1 file (checked 1 source file)
Why would it expect "Callable[[Config], int]"?
I'm using Python-3.8, and mypy==0.800
Solution 1:[1]
If you want the type of that field to be either a function of an int or a function of a str, you can do
class Config(NamedTuple):
func: Callable[[int], int] | Callable[[str], int]
This describes the union of two function types.
However, this is not a useful type. If Python had intersection types, this would be equivalent to
Callable[[int & str], int]
And int & str is, well, the empty type. There are no values which are both int and str at the same time. So this is a type of functions that can never be called. And isinstance won't help you here since you can't typecheck the declared argument types of a Callable.
As mentioned in the comments, you can do
Callable[[int | str], int]
but this is the type of functions that accept either an int or a string, not the type of functions that accept only one of the two selectively.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Silvio Mayolo |
