История изменений
Исправление byko3y, (текущая версия) :
а в питоне динамическая типизация, надеяться в нём на то что что-то там проверяется нельзя
Как же pydantic проводит проверку — задался я вопросом.
fields.py:_apply_validators
v = validator(cls, v, values, self, self.model_config)
...
return v, None
Кстати, передача ошибки через возвращаемое значение.
Смотрим на какой-нибудь «валидатор»:
def int_validator(v: Any) -> int:
if isinstance(v, int) and not (v is True or v is False):
return v
try:
return int(v)
except (TypeError, ValueError):
raise errors.IntegerError()
И, внезапно, выясняется, что эти валидаторы, на самом деле, просто пересоздают все входные данные. если они еще не являются экземплярами целевого типа. И это, на мой взгляд, есть самый адекватный способ проверки типов в питоне.
Напоминаю, что изменяемые (mutable) типы данных были не более чем оптимизацией ранних компьютеров с малым объемом памяти. Сами базовые типы построены на неизменяемых контейнерах, пересоздаваемых при изменении значения. Однако при этом Гвиде почему-то захотелось императивным с кучей изменяемых по месту типов данных, вроде того же массива — сравните с массивами PHP, которые имеют copy-on-write семантику, нивелирующую кучу граблей, на которые регулярно наступают питонисты.
К слову о массивах, fields.py:_validate_sequence_like
result = []
errors: List[ErrorList] = []
for i, v_ in enumerate(v):
v_loc = *loc, i
r, ee = self._validate_singleton(v_, values, v_loc, cls)
if ee:
errors.append(ee)
else:
result.append(r)
converted: Union[List[Any], Set[Any], FrozenSet[Any], Tuple[Any, ...], Iterator[Any], Deque[Any]] = result
...
return converted, None
Оно пересоздает заново весь массив, даже если входное значение уже является массивом. Конечно, это менее эффективно, чем copy-on-write и более эффективные варианты персистентных структур данных, но лучше чем питон ничего.
Исходная версия byko3y, :
а в питоне динамическая типизация, надеяться в нём на то что что-то там проверяется нельзя
Как же pydantic проводит проверку — задался я вопросом.
fields.py:_apply_validators
v = validator(cls, v, values, self, self.model_config)
...
return v, None
Кстати, передача ошибки через возвращаемое значение.
Смотрим на какой-нибудь «валидатор»:
def int_validator(v: Any) -> int:
if isinstance(v, int) and not (v is True or v is False):
return v
try:
return int(v)
except (TypeError, ValueError):
raise errors.IntegerError()
И, внезапно, выясняется, что эти валидаторы, на самом деле, просто пересоздают все входные данные. если они еще не являются экземплярами целевого типа. И это, на мой взгляд, есть самый адекватный способ проверки типов в питоне.
Напоминаю, что изменяемые (mutable) типы данных были не более чем оптимизацией ранних компьютеров с малым объемом памяти. Сами базовые типы построены на неизменяемых контейнерах, пересоздаваемых при изменении значения. Однако при этом Гвиде почему-то захотелось императивным с кучей изменяемых по месту типов данных, вроде того же массива — сравните с массивами PHP, которые имеют copy-on-write семантику, нивелирующую кучу граблей, на которые регулярно наступают питонисты.
К слову о массивах, fields.py:_validate_sequence_like
result = []
errors: List[ErrorList] = []
for i, v_ in enumerate(v):
v_loc = *loc, i
r, ee = self._validate_singleton(v_, values, v_loc, cls)
if ee:
errors.append(ee)
else:
result.append(r)
...
return converted, None
Оно пересоздает заново весь массив, даже если входное значение уже является массивом. Конечно, это менее эффективно, чем copy-on-write и более эффективные варианты персистентных структур данных, но лучше чем питон ничего.