5
votes

I was reading property(), which I understand is attribute access goes through the method specified in property(). But I got "RuntimeError: maximum recursion depth exceeded", when executed the following code.

class Property(object):

    def __init__(self):
        self.x = "Raj"

    def gettx(self):
        print "getting x"
        return self.x

    def settx(self, val):
        print "Setting x"
        self.x = val

    def dellx(self):
        print "deleting"
        return self.x

    x = property(gettx, settx, dellx, "I'm object property")


p = Property()
print "p.x", p.x
p.x = "R"
print "p.x:", p.x

Is it not possible to apply property in this way. Because it worked fine when 'self.x' changed to self._x and self.__x.

2

2 Answers

12
votes

The error is due to the following infinite recursion loop: you have defined a property x with uses the gettx, settx and deltx access methods, but the access methods themselves try to access the property x (i.e. call themselves).

You should write the code along the following lines:

class Property(object):

    def __init__(self):
        self.__x = "Raj"  # Class private

    def gettx(self):
        print "getting x"
        return self.__x

    def settx(self, val):
        print "Setting x"
        self.__x = val

    def dellx(self):
        print "deleting"
        return self.__x

    x = property(gettx, settx, dellx, "I'm object property")
0
votes

According to the python docs:

If c is an instance of C, c.x will invoke the getter, c.x = value will invoke the setter and del c.x the deleter.

So, your code line self.x = "Raj" essentially calls the method settx(self, val). Within that method the line self.x = val again calls the settx(self, val) method which in turn again calls the settx(self, val). Thus, we have an infinite loop.

So, the correct way to set the value of the property is self._x = value.

Correct code:

class Property(object):
    def __init__(self):
        self._x = 'Raj'

    def gettx(self):
        print "getting x"
        return self._x

    def settx(self, val):
        print "Setting x"
        self._x = val #stores the value in _x. writing self.x = val would cause an infinite loop

    def dellx(self):
        print "deleting"
        del self._x    

    x = property(gettx, settx, dellx, "I'm object property")

p = Property()
print "p.x", p.x
p.x = "R"
print "p.x:", p.x

Output:

p.x getting x
Raj
Setting x
p.x: getting x
R