Search code examples
pythonooppropertiespython-decoratorspython-class

Class objects contains both _<var> and <var> attributes when using property decorator


I have the following class. I want to keep _my_var = None if the user does not provide a value for that. They can use the setter to set it, where I enforce some validation

class A:
  _my_var = None

  @property
  def my_var(self):
      return self._my_var
   
  @property.setter
  def my_var(self, value)
      # Some validation
      return._my_var = value

I am creating an object in the following code

x = A()

When I look at the attributes x has

 _my_var: None
 my_var: None

When I set x._myvar = 10 both my_var and _my_var attributes are set to 10. I have a confusion about this. IS _my_var a field and my_var is a function? How can keep only _my_var as the attribute while enforcing the setter to set it?


Solution

  • It's because you made my_var a property, but in the function it returns self._my_var, so if you change the self._my_var to 10, and then you call the my_var function again, it would return the modified self._my_var value.

    Setting the my_var function to a @property could confuse you, it acts like it's just attribute of the class, but it's actually a function, just it is called without parenthesis. If you make it a regular function without @property like:

        def my_var(self):
            return self._my_var
      
    

    Then it would be more obvious that it's a function because you would call it like:

    x._myvar = 10
    print(x.my_var())
    

    Would give:

    10
    

    This would make it more obvious.

    To make it not change according to _my_var, change the function to an variable, so instead of:

        def my_var(self):
            return self._my_var
    

    Make it:

        self.my_var = int(self._my_var)