При наследовании модели Pydantic и попытке переопределить параметр списком подкласса mypy выдает ошибку типа. Базовый класс определяет параметр как список родительского класса, но при попытке переопределить его списком подкласса mypy считает его несовместимым.
Пример, который не работает:
from pydantic import BaseModel
class Name(BaseModel):
data: str
class EnglishName(Name):
data: str
class Animal(BaseModel):
name: list[Name]
class AmericaAnimal(Animal):
name: list[EnglishName] # Incompatible types in assignment (expression has type "list[EnglishName]", base class "Animal" defined the type as "list[Name]")
Напротив, следующий пример проходит:
from pydantic import BaseModel
class Name(BaseModel):
data: str
class EnglishName(Name):
data: str
class Animal(BaseModel):
name: Name
class AmericaAnimal(Animal):
name: EnglishName
Учитывая, что EnglishName наследуется от Name, тип должен быть совместим при использовании списка, но это не относится к mypy при переопределении списком подкласса.
Я попытался определить базовую модель Pydantic Name
с помощью data
поля типа str
. Затем я создал подкласс EnglishName
, унаследованный от Name
. Затем я определил еще одну базовую модель Pydantic Animal
с полем name
как списком Name
объектов. Однако когда я попытался переопределить это поле в подклассе AmericaAnimal
, чтобы оно было списком объектов EnglishName
, я ожидал, что тип будет совместимым, поскольку EnglishName
является подклассом Name
. Вместо этого я столкнулся с ошибкой несовместимости типов в mypy.
Ожидаемое поведение:
Я ожидал, что AmericaAnimal
примет список объектов EnglishName
в качестве поля name
из-за отношений наследования между Name
и EnglishName
.
Фактическое поведение:
Mypy выдал ошибку «Несовместимые типы при назначении», указывая на несоответствие типов между полем name
поля Animal
и переопределенным полем name
поля AmericaAnimal
.
TL;DR: используйте typing.Sequence
вместо list
.
Запуск mypy
в вашем коде приводит к следующей описательной ошибке:
$ mypy animal.py
animal.py:13: error: Incompatible types in assignment (expression has type "list[EnglishName]", base class "Animal" defined the type as "list[Name]") [assignment]
animal.py:13: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
animal.py:13: note: Consider using "Sequence" instead, which is covariant
Found 1 error in 1 file (checked 1 source file)
Проблема сводится к ковариации, как объяснено в этом ответе . Также ознакомьтесь с некоторыми предложениями в связанной документации.