The following code creates a dataclass Obj with an int field n with default value 0.
from dataclasses import dataclass, field
@dataclass
class Obj:
n: int = field(default_factory=int)
a = Obj()
print(a.n)
a.n = 0
Now, add an explicit __init__ constructor:
@dataclass
class Obj:
n: int = field(default_factory=int)
def __init__(self): # explicit constructor
pass
It now generates this error claiming that the Obj object has no attribute named n:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Input In [6], in <module>
8 pass
10 a = Obj()
---> 11 print(f'a.n = {a.n}')
AttributeError: 'Obj' object has no attribute 'n'
I thought maybe the explicit __init__ would override whatever field() is doing, but if we change from parameter default_factory to default, it works again:
@dataclass
class Obj:
n: int = field(default=3)
def __init__(self):
pass
a.n = 3
This behavior appears in both Python 3.8 and 3.10.
This module provides a decorator and functions for automatically adding generated special methods such as __init__() and __repr__() to user-defined classes.so no wonder why you get attribute error when overriding__init__againfield()to provide a default value for the field whether or not I wrote my own custom constructor. One of the nice things about dataclasses is that you can see the fields and default values all in one organized place, instead of having initialization scattered throughout a constructor. I didn't realize that the wayfield()worked was by putting code in the auto-generated constructor. It's confusing to me because you can give default values in other ways while writing a custom constructor (e.g., just writing= 3after the field name, or using the parameterdefault).