1

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 ?

flakes
  • 21,558
  • 8
  • 41
  • 88
Gabriel
  • 857
  • 10
  • 14

3 Answers3

2

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)
mujjiga
  • 16,186
  • 2
  • 33
  • 51
1
  1. There are no really private attributes in python. One can always access it, e.g. a._myvar = 2. It's just a convention - "We are all adults, you should not mess with this one" (see here for more details.
  2. The reason to have getters and setter in python is that you want to execute some extra code. Otherwise there is no need to use getters and setters.

Assuming that you indeed want to execute extra code at the time you set the value of attribute, class B is the correct implementation, because class A will not execute the extra code.

buran
  • 13,682
  • 10
  • 36
  • 61
-1

Well I'd like to bring attention there are some things wrong with your code. For example -

In your Class B, you're defining the variable as local in the init method but in your setter method you're using private method.

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

self.__myvar and self.var are two separate things.

So the below piece of code will result in an infinite loop


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
b = B(myvar=5)
print(b.myvar)


Now, I want to highlight that in Python you need to be careful with the private variable.

EXODIA
  • 908
  • 3
  • 10
  • 28