英文:
Why does Mypy report a subset of JSON as invalid?
问题
error: "return_json"的返回类型"List[Dict[str, JSON]]"与超类型"JsonReturner"中的返回类型"JSON"不兼容 [覆盖]
error: "return_json"的返回类型"Dict[str, List[JSON]]"与超类型"JsonReturner"中的返回类型"JSON"不兼容 [覆盖]
英文:
I have a base class that returns a JSON type. I then have subclasses that return more specific types that should I think be valid JSON types, but Mypy reports an error:
error: Return type "List[Dict[str, JSON]]" of "return_json" incompatible with return type "JSON" in supertype "JsonReturner" [override]
Have I misunderstood something or am I exploring the limits of the type-checking implementation?
Full example:
from typing import TypeAlias
JSON: TypeAlias = dict[str, "JSON"] | list["JSON"] | str | int | float | bool | None
class JsonReturner:
def return_json(self) -> JSON:
raise NotImplementedError("abstract base class")
class ListJsonReturner(JsonReturner):
def return_json(self) -> list[JSON]:
return []
class DictJsonReturner(JsonReturner):
def return_json(self) -> dict[str, JSON]:
return {}
class ListDictJsonReturner(JsonReturner):
def return_json(self) -> list[dict[str, JSON]]:
return []
class DictListJsonReturner(JsonReturner):
def return_json(self) -> dict[str, list[JSON]]:
return {}
$ mypy jsontypes.py
jsontypes.py:27: error: Return type "List[Dict[str, JSON]]" of "return_json" incompatible with return type "JSON" in supertype "JsonReturner" [override]
jsontypes.py:33: error: Return type "Dict[str, List[JSON]]" of "return_json" incompatible with return type "JSON" in supertype "JsonReturner" [override]
答案1
得分: 1
这一切都与方差有关。阅读 PEP-483 获取更多信息。
像 list
这样的通用类型是不变的:类型 list[T]
不是类型 list[U]
的子类型或超类型,除非 T
和 U
是相同的类型。
同样,dict
也是不变的,因为两个具体的字典类型只有在它们的键和值类型相同时才相同。
函数类型在其返回类型方面是协变的。对于固定的参数类型,Callable[..., R1]
是 Callable[..., R2]
的子类型,当 R1
是 R2
的子类型时。
联合类型的每个组件都是联合的子类型。
当你覆盖一个函数时,覆盖的类型必须是父函数的子类型。只要不更改参数类型,这意味着新的返回类型必须是原始返回类型的子类型。
在你的前两个覆盖中,返回类型是 JSON 的子类型。
在最后两个覆盖中,它们不是。list[dict[str, JSON]]
不是 JSON
的子类型,因为列表是不变的。dict[str, list[JSON]]
也不是 JSON
的子类型,因为字典也是不变的。
英文:
This all has to do with variance. Read PEP-483 for more information.
Generic types like list
are invariant: a type list[T]
is not a subtype nor a supertype of list[U]
unless T
and U
are the same type.
Similarly, dict
is invariant because a two concrete dict types are the same only if their key and value types are the same.
Function types are covariant in their return type. For a fixed argument type, Callable[..., R1]
is a subtype of Callable[..., R2]when
R1is a subtype of
R2`.
Each component of a union type is a subtype of the union.
When you override a function, the type of the override must be a subtype of the parent function. As long as you don't change the parameter types, this means the new return type must be a subtype of the original's return type.
In your first two overrides, the return types are subtypes of JSON.
In the last two, they are not. list[dict[str, JSON]]
is not a subtype of JSON
because lists are invariant. dict[str, list[JSON]]
is not a subtype of JSON
because dicts are invariant.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论