Callable является недействительным базовым классом? - PullRequest
0 голосов
/ 04 октября 2018

Может кто-нибудь объяснить, почему наследование от непараметризованного и параметризованного 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

при передаче в mypy вызывает ошибки как для Foo, так и Bar:

tmp.py:13: error: Invalid base class
tmp.py:19: error: Invalid base class

1 Ответ

0 голосов
/ 04 октября 2018

Это отчасти потому, что классы во время выполнения не могут на самом деле наследовать от функции или вызываемого объекта для начала, а отчасти потому, что вам не нужно явно наследовать от Callable, чтобы указать, что класс может быть вызван.

Например, следующие типы программ проверяются, как и ожидалось, с использованием 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

По сути, если у класса есть метод __call__, подразумевается, что класс также является вызываемым.

...