How to Define Class Attributes after Inheriting Pydantic's BaseModel?

Viewed 1461

In normal python classes I can define class attributes like

class Example:
  x = 3
  def __init__(self):
    pass

And if I then do Example.x or Example().x, I get 3.

When I inherit pydantic's BaseModel, I can't figure out how to define class attributes, because the usual way of defining them is overwritten by BaseModel.

For example:

class Example(BaseModel):
  x = 3

print(Example.x)
--> type object 'Example' has no attribute 'x'

I want to be able to define class level attributes. What is the proper method/syntax for this?

2 Answers

Okey-dokey, I eventually got to the bottom of it. The answer lies with how dataclasses handle class variables. (In retrospect that should have been obvious, but ya live and ya learn)

There exists a type called ClassVar. When a class's attribute is typed with ClassVar, then it becomes a class variable.

class Example(BaseModel):
  x: ClassVar[int] = 3
  y: int


# Usage
print(Example().x)
>>> ValidationError

print(Example.x)
>>> 3

You define the class level attributes correctly, but you are reading it out wrong. When reading out variables from this class, you should access the class over another variable defining that class. Like this:

from pydantic import BaseModel
class User(BaseModel):
  x = 3
user = User()
print(user.x)

what gives out: 3

Related