输入一个通用的可调用Bug



由于某些原因,不能正确键入可调用对象。下面的代码在Pylance和mypy中抛出错误。

示例代码

所以如果所有这些不变的,协变的和逆变的抛出一个异常。一个Callable如何是泛型的?

from typing import Generic, TypeVar, Any, Callable
class BaseModel:
...
class Model(BaseModel):
...
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_T_contra = TypeVar("_T_contra", contravariant=True)
class Dispatcher(Generic[_T, _T_co, _T_contra]):
def add_callback(self, func: Callable[[_T], Any]) -> None:
...
def add_callback_co(self, func: Callable[[_T_co], Any]) -> None:
...
def add_callback_contra(self, func: Callable[[_T_contra], Any]) -> None:
...
def add_mod(self, mod: _T) -> None:
...
module_dispatcher: Dispatcher[BaseModel, BaseModel, BaseModel] = Dispatcher()
def call_me(model: Model) -> None:
...
module_dispatcher.add_callback(call_me)  # Throws incompatibility
module_dispatcher.add_callback_co(call_me)  # Throws incompatibility
module_dispatcher.add_callback_contra(call_me)  # Throws incompatibility
module_dispatcher.add_mod(Model())  # This is OK

mypy/pylance输出

我只抱怨Callableadd_mod方法进行泛型类型推断。

/tmp/testing.py:35: error: Argument 1 to "add_callback" of "Dispatcher" has incompatible type "Callable[[MyModel], None]"; expected "Callable[[MyBaseModel], Any]"

这是因为函数的类型在其实参中是逆变的。

参数funcmodule_dispatcher.add_callback必须能够取MyBaseModel的任何实例。

要了解原因,请注意您也可以执行module_dispatcher.add_mod(MyOtherModel())(当然,假设是issubclass(MyOtherModel, MyBaseModel))。现在call_me将以而不是MyModel的实例来调用。

我建议的解决方案:

def call_me(model: MyBaseModel) -> None:
...

如果这对你不起作用,我将需要更多地了解Dispatcher类所需的行为。

最新更新