当尝试使用类型的 TypeVar 来启用具有返回类型的泛型时,我遇到了 mypy 错误,即bound在比较字典的类型和函数的预期返回类型时未考虑参数。
下面是我面临的情况的一个例子:
from typing import Dict, List, Type, TypeVar
class Bird:
def call(self):
print(self.sound)
class Chicken(Bird):
def __init__(self):
self.sound = "bok bok"
class Owl(Bird):
def __init__(self):
self.sound = "hoot hoot"
T = TypeVar("T", bound=Bird)
class Instantiator:
def __init__(self, birds: List[Type[Bird]]):
self._bird_map: Dict[Type[Bird], Bird] = {}
for bird in birds:
self._bird_map[bird] = bird()
def get_bird(self, bird_type: Type[T]) -> T:
return self._bird_map[bird_type]
Run Code Online (Sandbox Code Playgroud)
运行 mypy 验证器将显示:temp.py:29: error: Incompatible return value type (got "Bird", expected "T")
它Instantiator被用作一种“跟踪器”,用于实例化每种鸟类。当尝试基于类类型检索实例化对象时,这就是需要使用泛型的原因,否则稍后键入的字段会抱怨使用类Bird而不是 或Chicken之一Owl。
我在这里使用不正确吗TypeVar?是否有不同的方法来处理结构?这是 mypy 的疏忽吗?
这是因为您定义了一个仅包含基类对象的字典Bird,但在函数中get_bird您试图返回基类类型的对象,而可能需要派生类的对象。Mypy不会进行Base -> Derived演员表。
您还可以创建__init__一个通用函数。
T = TypeVar("T", bound=Bird)
class Instantiator():
def __init__(self, birds: List[Type[T]]):
self._bird_map: Dict[Type[T], T] = {}
for bird in birds:
self._bird_map[bird] = bird()
def get_bird(self, bird_type: Type[T]) -> T:
return self._bird_map[bird_type]
Run Code Online (Sandbox Code Playgroud)
或者明确使用cast:
class Instantiator:
def __init__(self, birds: List[Type[Bird]]):
self._bird_map: Dict[Type[Bird], Bird] = {}
for bird in birds:
self._bird_map[bird] = bird()
def get_bird(self, bird_type: Type[T]) -> T:
return cast(T, self._bird_map[bird_type])
Run Code Online (Sandbox Code Playgroud)