Неожиданное поведение PyDantic моделей при их инициализации

Работаю с PyDantic моделями и заметил, что модели унаследованные от BaseModel не проверяют именованные параметры, в отличии от обычных экземпляров классов. Кто-нибудь сталкивался с похожим поведением. Полагаю, что у них дескрипторы классов как-то странно прописаны. Может есть инструментарий в самой библиотеке как-то на это повлиять?

from pydantic import BaseModel


class OrdinaryModel:
    def __init__(self, a, b):
        self.a = a
        self.b = b


class PydanticModel(BaseModel):
    a: int
    b: str


if __name__ == '__main__':
    kws = {'a':34, 'b':323, 'c':54}
    ord_model = OrdinaryModel(**kws)
    pyd_model = PydanticModel(**kws)
    print(pyd_model.dict()) # Тут никакой ошибки нету
    print(ord_model.__dict__) # Здесь же выскакивает ожидаемая ошибка TypeError

Ошибка:

TypeError: __init__() got an unexpected keyword argument 'c'


Ответы (1 шт):

Автор решения: gil9red

Ошибка говорит о лишнем параметре c в конструкторе:

TypeError: init() got an unexpected keyword argument 'c'

Причина в том, что код вида:

kws = {'a':34, 'b':323, 'c':54}
ord_model = OrdinaryModel(**kws)

Аналогичен:

ord_model = OrdinaryModel(a=34, b=323, c=54)

Но, т.к. у вас в конструкторе нет параметра c, то и получаете ожидаемую ошибку.

Как вариант, вы можете добавить магические параметры *args, **kwargs, чтобы не объявленные явно параметры попали в них.

Попробуйте:

class OrdinaryModel:
    def __init__(self, a, b, *args, **kwargs):
        self.a = a
        self.b = b

if __name__ == '__main__':
    kws = {'a':34, 'b':323, 'c':54}
    ord_model = OrdinaryModel(**kws)
    print(ord_model.__dict__)
    # {'a': 34, 'b': 323}

PS.

А в типе от BaseModel из pydantic нет заданного конструктора, значит он его заранее создал и, возможно, как раз через **kwargs

→ Ссылка