我正在尝试正确注释我的代码。这是重现我的问题的示例片段:
from pydantic import BaseModel
from typing import TypeVar
class Shape(BaseModel):
name: str
class Circle(Shape):
diameter: float
class Square(Shape):
side: float
class Triangle(Shape):
base: float
height: float
T = TypeVar("T")
def generate_shapes(shapes: list[type[T]]) -> list[T]:
generated_shapes = []
for shape in shapes:
if shape == Circle:
generated_shapes.append(Circle(name=shape.__name__, diameter=10))
elif shape == Square:
generated_shapes.append(Square(name=shape.__name__, side=10))
elif shape == Triangle:
generated_shapes.append(Triangle(name=shape.__name__, base=10, height=10))
return generated_shapes
if __name__ == "__main__":
result = generate_shapes([Circle, Triangle])
实际上,代码看起来不错,但 mypy 抱怨。特别是我试图理解的错误是:
“generate_shapes”的参数 1 具有不兼容的类型 “列表[模型元类]”;预期“列表[类型[从不]]”
我的目标是能够从输入推断输出列表类型。看来使用这个注解vscode是能够看懂的:
我的基本理解是 mypy 抱怨是因为列表是可变的并且不能协变。所以我担心我想要实现的目标没有出路(vscode 推断 + mypy 快乐)?
你的函数并不是很通用。实际上,它需要一个
Shape
类列表并返回 Shape
列表。没有真正的理由“允许”使用更通用的列表作为参数。如果调用者以某种方式拥有像 [Circle, Triangle, 1, Square]
这样的列表,他们可以负责首先删除非 Shape
子类元素。此外, generated_shapes
的初始推断类型是
list[Any]
,通过第一次尝试将任何内容追加到列表中,它会缩小为 list[Circle]
。如果您的函数不是通用的,您可以预先明确 generated_shapes
的类型。 (mypy
并没有从函数声明的返回类型推断出 generated_shapes
的类型。)def generate_shapes(shapes: list[type[Shape]]) -> list[Shape]:
generated_shapes: list[Shape] = []
for shape in shapes:
if shape == Circle:
generated_shapes.append(Circle(name=shape.__name__, diameter=10))
elif shape == Square:
generated_shapes.append(Square(name=shape.__name__, side=10))
elif shape == Triangle:
generated_shapes.append(Triangle(name=shape.__name__, base=10, height=10))
return generated_shapes