NNN
NNN

Reputation: 591

passing instance variable to a setter

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

Answers (1)

Carlo Zanocco
Carlo Zanocco

Reputation: 2019

I'd like to know why 'Case 3' does not work, and if there is a way of getting 'Case 3' to work

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__.


How is self passed to the check_prop in the three case?

Case 1

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)

Case 2

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.

Case 3

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.


Note

  • 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

Related Questions