Reputation: 703
class P:
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 = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
I am trying to learn 'getters' and 'setters' methods. When I create an instance with these inputs:
p1 = P(1001)
print(p1.x)
p1.x = -12
print(p1.x)
I get as outputs:
1001
-12
I don't know why do I get 1001
and -12
instead of 1000
and 0
.
Upvotes: 1
Views: 102
Reputation: 60997
Your real problem is that you're using Python 2.x with old-style classes. Your code as shown will work as you expect on Python 3.x (except for the broken indentation, of course). It will also work on Python 2.x if you make P
a new-style class by explicitly inheriting from object
(e.g. declare it as class P(object):
).
In an old-style class, the problem is that your setter and getter methods are both named x
, and both are competing for entries in the same namespace.
When you have code like:
@x.setter
def x(self, x):
...
What happens is that a new function object (confusingly, named x
) is created with the code you specify, then x.setter(x_function_object)
is called, and whatever x.setter
returns (which will be a descriptor object with __get__
and __set__
defined) is assigned to x
in the namespace dictionary that is passed to the metaclass's __new__
method and used to build the class's type.
However, in an old-style class, when you write self.x = ...
then it will invoke __setattr__
directly rather than using the descriptor protocol (self.__dict__['x'].__set__(x, ...)
). Thus the assignment to self.x
in your __init__
method will overwrite the setter method instead of calling it.
Upvotes: 8