Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pydantic: dataclass vs BaseModel

What are the advantages and disadvantages of using Pydantic's dataclass vs BaseModel? Are there any performance issues or is it easier to Pydantic's dataclass in the other python module?

like image 875
sacherus Avatar asked May 25 '20 22:05

sacherus


2 Answers

Your question is answered in Pydantic's documentation, specifically:

Keep in mind that pydantic.dataclasses.dataclass is a drop-in replacement for dataclasses.dataclass with validation, not a replacement for pydantic.BaseModel (with a small difference in how initialization hooks work). There are cases where subclassing pydantic.BaseModel is the better choice.

For more information and discussion see samuelcolvin/pydantic#710.

The discussion link will give you some of the context you are looking for. In general, Pydantic's BaseModel implementation is not bound to behave the same as Python's dataclass implementation. The example cited in the issue above is one good example:

from pydantic import BaseModel
from pydantic.dataclasses import dataclass
from typing import List

@dataclass
class A:
    x: List[int] = []

# Above definition with a default of `[]` will result in:
#   ValueError: mutable default <class 'list'> for field x is not allowed: use default_factory
# If you resolve this, the output will read as in the comments below.

class B(BaseModel):
    x: List[int] = []

print(A(x=[1, 2]), A(x=[3, 4])) # Output: A(x=[1, 2]) A(x=[3, 4])
print(B(x=[1, 2]), B(x=[3, 4])) # Output: x=[1, 2] x=[3, 4]

If what you want first and foremost is dataclass behavior and then to simply augment it with some Pydantic validation features, the pydantic.dataclasses.dataclass approach may be what you want. Otherwise, BaseModel is probably what you want.

like image 99
Jeffrey Wilges Avatar answered Nov 16 '22 00:11

Jeffrey Wilges


The init Function for BaseModel works differently than the init for dataclass

@dataclass()
class Foo:
    number: int

class Bar(BaseModel):
    number: int

f = Foo(number = 1.4)
b = Bar(number = 1.4)
print(f)
print(b)

Output:

Foo(number=1.4)
number=1
like image 22
Phil997 Avatar answered Nov 16 '22 01:11

Phil997