Let's consider the two implementations :
class A:
def __init__(self, myvar):
self._myvar = myvar #
@property
def myvar(self):
print("GET")
return self._myvar
@myvar.setter
def myvar(self, newvar):
print("SET")
self._myvar = newvar
and
class B:
def __init__(self, myvar):
self.myvar = myvar
@property
def myvar(self):
print("GET")
return self._myvar
@myvar.setter
def myvar(self, newvar):
print("SET")
self._myvar = newvar
The only difference is in the __init__
where we initialised _myvar in class A and myvar in class B
a = A(myvar=5)
print(a.myvar)
will output
GET
5
and
b = B(myvar=5)
print(b.myvar)
will output
SET
GET
5
All in all, from my understanding, the only difference in the two implementations is in the init. An instance of class A will set _myvar directly while an instance of class B will go through myvar.setter to set _myvar. So my question is the following : Which implementation is considered more pythonic ? Is there a reason to use one over the other ?
class B
is better way of doing.
Lets say you have some validation steps in setter
, for example you want to make sure only values in certain range are set to myvar
. class B
will make sure that the validation steps are run even via constructor. However in case of class A
, you are directly updating the variable and in this case the validation steps sitting inside the setter
method are skipped.
class EvenOnly_A:
def __init__(self, myvar):
self._myvar = myvar #
@property
def myvar(self):
return self._myvar
@myvar.setter
def myvar(self, newvar):
assert newvar%2 == 0
self._myvar = newvar
class EvenOnly_B:
def __init__(self, myvar):
self.myvar = myvar
@property
def myvar(self):
return self._myvar
@myvar.setter
def myvar(self, newvar):
assert newvar%2 == 0
self._myvar = newvar
a = EvenOnly_A(3)
b = EvenOnly_B(3)