Can someone explain why inheriting from unparameterized and parameterized Callable
:
from typing import Callable
from typing import NoReturn
from typing import TypeVar
T = TypeVar('T', str, int)
C = Callable[[T], NoReturn]
class Foo(Callable):
def __call__(self, t: T):
pass
class Bar(C):
def __call__(self, t: T):
pass
when passed to mypy raises errors for both Foo
and Bar
:
tmp.py:13: error: Invalid base class
tmp.py:19: error: Invalid base class
This is in part because classes at runtime can't really inherit from a function or a callable to begin with, and in part because you don't need to explicitly inherit from Callable
to indicate that a class is callable.
For example, the following program typechecks as expected using mypy 0.630:
from typing import Callable, Union, NoReturn, List
class Foo:
def __call__(self, t: Union[str, int]) -> NoReturn:
pass
class FooChild(Foo): pass
class Bad:
def __call__(self, t: List[str]) -> NoReturn:
pass
def expects_callable(x: Callable[[Union[str, int]], NoReturn]) -> None:
pass
expects_callable(Foo()) # No error
expects_callable(FooChild()) # No error
expects_callable(Bad()) # Error here: Bad.__call__ has an incompatible signature
Basically, if a class has a __call__
method, it's implicitly assumed that class is also a callable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With