I have been here:
and could not find a direct answer to why this simple code works fine...
class Vehicle:
def __init__(self, wheels: int = 10):
self.wheels = wheels # -> calls the setter method
@property
def wheels(self) -> int:
print("getting wheels")
return self._wheels
@wheels.setter
def wheels(self, wheels: int):
print("setting wheels to", wheels)
self._wheels = wheels
v = Vehicle()
number = v.wheels # -> calls the getter method
print(number)
# last output: 10
...but this one does not (using dataclass
):
from dataclasses import dataclass
@dataclass
class Vehicle:
wheels: int = 10
@property
def wheels(self) -> int:
print("getting wheels")
return self._wheels
@wheels.setter
def wheels(self, wheels: int):
print("setting wheels to", wheels)
self._wheels = wheels
v = Vehicle()
number = v.wheels
print(number)
# output: <property object at 0x000002042D70DDB0>
even when the official documentation of dataclass
tells explicitly in the beginning that the decorator @dataclass
adds exactly the __init__
method from the first code, i.e., this code:
@dataclass
class Vehicle:
wheels: int = 10
should add this __init__
:
def __init__(self, wheels: int = 10):
self.wheels = wheels
The private attribute _wheels
is accessed only inside the property
's methods, as it should be (to isolate it).
I found in others threads (listed above) that this attribute is manipulated outside the methods, exposed as 'public', which is not desired in some cases.
That's a bug in your code.
This code:
wheels: int = 10
sets wheels
to 10
, then this code immediately after:
@property
def wheels(self) -> int:
print("getting wheels")
return self._wheels
sets wheels
to a property
instance.
@dataclass
can't see the 10
. Your 10
is gone. The annotation remains, so @dataclass
creates a wheels
field, but your field's default value is a property
instance, not 10
.