new·Earn with mozg — 20% of every monthSend somebody here and take a fifth of every plan payment they make, for as long as they keep paying — not a bounty on the first invoice. Your handle is the link, the window is thirty days, and the commission lands on your balance the second they pay. Free to join: if you have signed in, you already have the link. mozg.sh/earnall news →
mozg.beta
Sign in

Pydantic · Concepts · all subjects

dataclasses

17 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Pydantic dataclasses provide validation without BaseModel

Pydantic dataclasses allow you to get the same data validation on standard dataclasses without using BaseModel. They are decorated with @pydantic.dataclasses.dataclass and support Pydantic validation on stdlib dataclass syntax.

Pydantic dataclasses are not a replacement for Pydantic models

Pydantic dataclasses provide similar functionality to stdlib dataclasses with Pydantic validation added, but they are not a complete replacement for Pydantic models. There are cases where using Pydantic models is the better choice.

Wrapping Pydantic dataclasses with TypeAdapter for validation and serialization

Since Pydantic dataclasses do not have the various methods to validate, dump, and generate JSON Schema that models have, you can wrap the dataclass with a TypeAdapter to access methods like dump_python() and validate_python().

Validators work with Pydantic dataclasses

You can use @field_validator decorators on Pydantic dataclasses. Validators are applied during initialization with the same modes (before, after) as with Pydantic models.

__post_init__() is called between before and after validators in Pydantic dataclasses

The dataclass __post_init__() method is supported in Pydantic dataclasses and will be called between the calls to before and after model validators, providing a predictable initialization order.

Generic dataclasses do not validate parameterized types

Generic Pydantic dataclasses are supported, but using a parameterized dataclass like Foo[int] will not perform validation for that specific type parameter. Unlike generic Pydantic models, parameterized dataclasses are generic aliases, not proper type objects. To work around this, wrap Foo[int] with TypeAdapter.

Pydantic dataclasses accept both Pydantic Field() and stdlib field()

You can use both pydantic.Field() and dataclasses.field() functions when defining fields in Pydantic dataclasses. This allows mixing Pydantic-specific features like constraints (ge, le) with stdlib dataclass features like default_factory and metadata.

Pydantic dataclasses can inherit from stdlib dataclasses

Stdlib dataclasses (nested or not) can be inherited by Pydantic dataclasses, and Pydantic will automatically validate all inherited fields. The @pydantic.dataclasses.dataclass decorator can also be applied directly to a stdlib dataclass to create a new subclass with Pydantic validation.

Stdlib dataclasses used in Pydantic models get validated

When a standard library dataclass is used as a field annotation in a Pydantic model, Pydantic dataclass, or TypeAdapter, Pydantic will apply validation. Using a stdlib or Pydantic dataclass as a field annotation is functionally equivalent in terms of validation.

is_pydantic_dataclass() function to check if a dataclass is from Pydantic

Use pydantic.dataclasses.is_pydantic_dataclass() to check if a type is specifically a Pydantic dataclass. The stdlib dataclasses.is_dataclass() will return True for both stdlib and Pydantic dataclasses, so is_pydantic_dataclass() is needed to distinguish them.

rebuild_dataclass() function to rebuild dataclass schema

The pydantic.dataclasses.rebuild_dataclass() function can be used to rebuild the core schema of a dataclass, similar to the rebuild_model() function for models.

Extra data behavior in Pydantic dataclasses

In Pydantic dataclasses, extra data is not included in serialization. Unlike Pydantic models, there is no way to customize validation of extra values using the __pydantic_extra__ attribute.

Example: Pydantic dataclass with validation

```python from datetime import datetime from pydantic.dataclasses import dataclass @dataclass class User: id: int name: str = 'John Doe' signup_ts: datetime | None = None user = User(id='42', signup_ts='2032-06-21T12:00') print(user) # User(id=42, name='John Doe', signup_ts=datetime.datetime(2032, 6, 21, 12, 0)) ``` This shows Pydantic dataclasses automatically coercing string input to int and datetime types.

Example: Using TypeAdapter with Pydantic dataclasses

```python from pydantic import TypeAdapter from pydantic.dataclasses import dataclass @dataclass class Foo: f: int foo = Foo(f=1) TypeAdapter(Foo).dump_python(foo) # {'f': 1} TypeAdapter(Foo).validate_python({'f': 1}) # Foo(f=1) ``` This shows wrapping a dataclass with TypeAdapter to access validation and serialization methods.

Example: Field validators with Pydantic dataclasses

```python from pydantic import field_validator from pydantic.dataclasses import dataclass @dataclass class DemoDataclass: product_id: str @field_validator('product_id', mode='before') @classmethod def convert_int_serial(cls, v): if isinstance(v, int): v = str(v).zfill(5) return v print(DemoDataclass(product_id='01234')) # DemoDataclass(product_id='01234') print(DemoDataclass(product_id=2468)) # DemoDataclass(product_id='02468') ``` This shows using @field_validator with Pydantic dataclasses.

Example: Inheritance from stdlib dataclasses

```python import dataclasses import pydantic @dataclasses.dataclass class Z: z: int @dataclasses.dataclass class Y(Z): y: int = 0 @pydantic.dataclasses.dataclass class X(Y): x: int = 0 foo = X(x=b'1', y='2', z='3') print(foo) # X(z=3, y=2, x=1) ``` This shows Pydantic dataclasses validating inherited fields from stdlib dataclasses.

Example: __post_init__() execution order with validators

```python from pydantic_core import ArgsKwargs from typing_extensions import Self from pydantic import model_validator from pydantic.dataclasses import dataclass @dataclass class User: birth: 'Birth' @model_validator(mode='before') @classmethod def before(cls, values: ArgsKwargs) -> ArgsKwargs: print(f'First: {values}') return values @model_validator(mode='after') def after(self) -> Self: print(f'Third: {self}') return self def __post_init__(self): print(f'Second: {self.birth}') user = User(**{'birth': {'year': 1995, 'month': 3, 'day': 2}}) ``` This shows the execution order: before validator, then __post_init__(), then after validator. The values parameter in 'before' mode is ArgsKwargs, not a dict.

Give your agent this brain