Reputation: 591
I'm trying to pass an instance variable to a method which returns a property (setter and getter), and I can't seem to do so. I want the method which returns a property in a separate class so that I can use inheritance and add additional checks as desired. Please see the code below:
class CheckProperty():
def prop_check(self,name,maximum):
private_name = '_'+name
@property
def prop(self2):
return getattr(self2,private_name)
@prop.setter
def prop(self2,x):
if ( x > maximum ):
print('In CheckProperty: Trying to set number to a value > maximum')
x = maximum
setattr(self2,private_name,x)
return prop
class TestSetter():
def __init__(self,maximum):
self.maximum = maximum
self._number1 = 0
self._number2 = 0
self._number3 = 0
self.number1 = 10
self.number2 = 10
# CASE 1
# creating setters manually works, I can create a getter and setter for the
# variable/property number which checks against self.maximum
# so, self.maximum gets passed (somehow) to the setter
@property
def number1(self):
return self._number1
@number1.setter
def number1(self,x):
self._number = x
if ( x > self.maximum ):
print('Simple setter/getter: Trying to set number to a value > self.maximum')
self._number = self.maximum
# CASE 2
# this works as expectd. I can't set the value of number1 to greater than 3
number2 = CheckProperty().prop_check('number2',3)
# CASE 3
# the following, however, does not work. Python says: name 'self' is not defined
# which makes sense, but begs the question: how does self get passed to the
# property (descriptor) in CASE 1
# number3 = CheckProperty().prop_check('number3',self.maximum)
This code can be invoked with:
# first import the classes by using something like
# from <module> import TestSetter
tt = TestSetter(3)
tt.number1 = 5
tt.number2 = 10
Upvotes: 1
Views: 692
Reputation: 2019
The self
is meant to refer to a class instance. You use self
where it is not defined, right out in the class where no specific object is yet known.
There is no way to make the Case 3 working, also declaring a static variable in the class. the __init__
method isn't run until TestSetter
is instantiated. number3 = ..
is run whenever the class definition is encountered in the code, so the value of the static variable will not be the one passed as argument in the __init__
.
check_prop
in the three case?The property()
return a special descriptor object
When you write:
@property
def number1(self):
return self._number1
You are creating an object of class property by passing the function number1
as the first parameter to its constructor. Remember that functions in python can be passed around like any other object, because they are also objects.
It is equal to:
def number1(self):
return self._number1
number1 = property(number1)
Instances of self
get passed to functions (and also to methods, and even operators) all the time. Just calling CheckProperty().prop_check('number2',3)
the self is implict passed to prop_check
.
This case use the same logic as the Case 2 so you expect that self
is automatically passed to the prop_check
, and it do, exactly as the Case 2, but the problem is that you are trying to access self.maximum
and pass it as parameter. In the class is not defined yet.
In the Case 1 the maximum value is 3
as you expect because the above explaination, so the value that you set in TestSetter(3)
call is taken.
In the Case 2 the maximum value is 3 because you declared number2
as number2 = CheckProperty().prop_check('number3',3)
. That means that if you change the value of TestSetter(3)
call to another value, 3
is always taken.
In the Case 3 the self
is not recognized but the logic is the same as the Case 2, if you replace the self.maximum
with a number it works exactly as the Case 2.
Upvotes: 4