У меня есть следующий код:
from typing import Callable
MyCallable = Callable[[object], int]
MyCallableSubclass = Callable[['MyObject'], int]
def get_id(obj: object) -> int:
return id(obj)
def get_id_subclass(obj: 'MyObject') -> int:
return id(obj)
def run_mycallable_function_on_object(obj: object, func: MyCallable) -> int:
return func(obj)
class MyObject(object):
'''Object that is a direct subclass of `object`'''
pass
my_object = MyObject()
# works just fine
run_mycallable_function_on_object(my_object, get_id)
# Does not work (it runs, but Mypy raises the following error:)
# Argument 2 to "run_mycallable_function_on_object" has incompatible type "Callable[[MyObject], int]"; expected "Callable[[object], int]"
run_mycallable_function_on_object(my_object, get_id_subclass)
Поскольку MyObject
наследуется от object
, почему MyCallableSubclass
не работает везде, где работает MyCallable
?
Я немного читал о Принцип подстановки Лисков, а также ознакомился с документами Mypy о ковариантности и контравариантность. Однако даже в самих документах они приводят очень похожий пример, где говорят
Callable
является примером типа, который ведет себя контравариантно в отношении типов аргументов, а именноCallable[[Employee], int]
является подтипомCallable[[Manager], int]
.
Тогда почему использование Callable[[MyObject], int]
вместо Callable[[object], int]
вызывает ошибку в Mypy?
В общем у меня два вопроса:
- Почему это происходит?
- Как это исправить?