con't define variable in pydantic init function

Question:

i want to define a Base model that inherits from pydantic BaseModel like bellow

class BaseDomain(BaseModel):

    def __init__(self, **kwargs):
        self.__exceptions = []

    def add_error(self, exception: GeneralException):
        self.__exceptions.append(exception)

but i get this error when i use Product model that inherits from BaseDomain

ValueError: "Product" object has no field "_BaseDomain__exceptions"
Asked By: Mahdi Sorkhmiri

||

Answers:

Because you have overidden pydantic’s init method that is executed when a class that inherits from BaseModel is created. you should call super()

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.__exceptions = []

EDIT

It seems that pydantic throws that error because it validates __exceptions as an input and throws an error because it isn’t defined in the classes annotations

Try this:

from typing import List, Any

class BaseDomain(BaseModel):
    __exceptions:List[Any] = []

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
Answered By: jeremy302

Please introduce super in the init method.

def __init__(self,**kwargs):
super().__init
Answered By: Shuvam Paul

Another version with "underscore_attrs_are_private" option

from typing import List, Optional, Any
from pydantic import BaseModel

class BaseDomain(BaseModel):
    __exceptions: Optional[List[Any]] = None
    class Config:
        underscore_attrs_are_private = True

    def add_error(self, exception: Exception):
        if self.__exceptions is None:
            self.__exceptions = []
        self.__exceptions.append(exception)
        
    def get_exceptions(self):
        return self.__exceptions
        
class Item(BaseDomain):
    name: str

item = Item(name="test")
print(item.get_exceptions())
item.add_error(Exception("test"))
print(item.get_exceptions())
Answered By: Artur Shiriev

Use PrivateAttr with default factory:
https://pydantic-docs.helpmanual.io/usage/models/#private-model-attributes

from pydantic import BaseModel, PrivateAttr

class MyClass(BaseModel):
    normal_value: int
    __private_value__: Dict[str, int] = PrivateAttr(default_factory=dict)
    _private_list: List = PrivateAttr(default_factory=list)

Works both with one underscore or two undescores in names.

Answered By: Denis Krumko
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.