31

I have this project where my base class and my sub-classes implement pydantic.BaseModel:

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

@dataclass
class User(BaseModel):
    id: int 

@dataclass
class FavoriteCar(User):
    car_names: List[str] 

car = FavoriteCar(id=1, car_names=["Acura"])
print(f"{car.id} {car.car_names[0]}")

But this error appears:

    self.__fields_set__.add(name)
E   AttributeError: __fields_set__

Does someone mind explaining what is going on? The reason why I want to use pydantic is because I need a way to quickly convert Python objects to dict (or JSON) and back.

Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
Kendrick Lamar
  • 781
  • 2
  • 8
  • 18
  • I updated the post with a better example. This is similar to the code that I have, in my src. – Kendrick Lamar Feb 10 '20 at 21:36
  • 1
    Looks like you can reproduce this without the subclass `FavoriteCar`, and `dataclass` and `BaseModel` conflict in some way. – chepner Feb 10 '20 at 21:48
  • I did not provide a full example earlier. I solved the issue thanks to everyones help. You cannot use the @dataclass decorator with pydantic, I am not 100% certain as to why, but it might be because pydantic does something special to the annotated data in the background. – Kendrick Lamar Feb 10 '20 at 21:52
  • Seems like I skipped over something very important: https://pydantic-docs.helpmanual.io/usage/dataclasses/ – Kendrick Lamar Feb 10 '20 at 21:59

2 Answers2

29

You need to decide whether to inherit from pydantic.BaseModel, or whether to use the @dataclass decorator (either from dataclasses, or from pydantic.dataclasses).

Either is fine, but you cannot use both, according to the documentation (bold face added by myself):

If you don't want to use pydantic's BaseModel you can instead get the same data validation on standard dataclasses

Peter Thomassen
  • 1,671
  • 1
  • 16
  • 28
1
E   AttributeError: __fields_set__

The first part of your question is already answered by Peter T as Document says - "Keep in mind that pydantic.dataclasses.dataclass is a drop-in replacement for dataclasses.dataclass"

The second part is that you wanted to convert them as dict.

The reason why I want to use pydantic is because I need a way to quickly convert Python objects to dict (or JSON) and back

To answer to that part of your question you can use asdict of dataclass itself source

from dataclasses import dataclass, asdict
from typing import List


@dataclass
class Point:
     x: int
     y: int

@dataclass
class C:
     l: List[Point]

p = Point(10, 20)
assert asdict(p) == {'x': 10, 'y': 20}

c = C([Point(0, 0), Point(10, 4)])
assert asdict(c) == {'l': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}

There is discussion about these module level helper function(.asdict & .astuple) that they arent PEP8 compliant (should be as_dict() and as_tuple()) however finally they decided to keep consistency with namedtuple._asdict() and attr.asdict(). source

Shakeel
  • 1,869
  • 15
  • 23