I would like to use a dataclass with an invariant that should not change during the lifetime of such instantiated objects. To indicate that the instance variables of these objects are private, their names are prefixed with an underscore. These instance variables can easily be accessed with the use of properties, as demonstrated with the example code below:
from dataclasses import dataclass
@dataclass
class C():
_x: int = 3
@property
def x(self) -> int:
return self._x
def p(self) -> None:
print(self._x)
The problem arises when I want to call the constructor of this class with explicit keyword arguments. To do so, I now have to provide the names of the instance variables with an underscore as well. This seems really counterintuitive, since the private variables are now accessed from outside of the class.
a = C() # sets 'a.x' to 3
a.p() # prints 3
b = C(5) # sets 'b.x' to 5
b.p() # prints 5
c = C(_x=7) # sets 'c.x' to 7
c = C(x=7) # error: unexpected keyword argument 'x'
One way to solve this problem, is to simply provide an explicit constructor with matching arguments:
def __init__(self, x: int = 3) -> None:
self._x = x
However, this also seems to be dreadfully counterintuitive as this approach contradicts the whole notion of a dataclass. Is there a way to use a dataclass in combination with properties that allows me to use explicit keyword arguments when constructing such objects without having to access/acknowledge instance variables intended to be private?