Home > Mobile >  Why is `self.__x` not working but `self.y` is?
Why is `self.__x` not working but `self.y` is?

Time:02-15

I am learning to use @property decorators. I am giving two codes below with a little variation:

Code 1

class P2:
    def __init__(self, x):
        self.x = x
    @property
    def x(self):
        return self.y
    @x.setter
    def x(self, x):
        if x < 0:
            self.y = x
        elif x > 1000:
            self.y = 1000
        else:
            self.y = x
   
p1 = P2(7600)
print(p1.y)

Code2

class P2:
    def __init__(self, x):
        self.x = x
    @property
    def x(self):
        return self.__x
    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = x
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x
   
p1 = P2(7600)
print(p1.__x)

To obtain the code2 I replace y by __x in code1. But the issue is that the code1 is running perfectly fine but the code2 is giving an error 'P2' object has no attribute '__x'.

My understanding is that y and __x are merely two variables, they should behave in same way, so in my opinion code2 and code1 are identical and both should give same output.

But it is not happening, what is wrong in my understanding? Please help.

CodePudding user response:

Properties that are prepended with a double underscore are pseudo-private. (There is no notion of completely private variables in Python, unlike Java or C .)

To access pseudo-private member variables, replace the double underscore with _<name of your class>__ (i.e. an underscore, followed by the class name, followed by two underscores). That being said, if you need to do this, you should consider why the variable is pseudo-private in the first place.

class P2:
    def __init__(self, x):
        self.x = x
    @property
    def x(self):
        return self.__x
    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = x
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x
   
p1 = P2(7600)
print(p1._P2__x) # Prints 1000
  • Related