Search code examples
pythonpython-3.xrecursiondecoratorgetter-setter

Why does trying to set "points" via Python properties cause infinite recursion?


Why does trying to set “points” via Python properties cause infinite recursion?

Using Python 3

import Task

myTask = Task.Task("Test",-5)

myTask.points = -7

print(myTask)

class Task:

def __init__(self,name="",points=0,times_done=0):
    self.name = name
    self.points = points
    self.times_done = times_done

@property
def points(self):
    return self.points

@points.setter
def points(self, points):
    if (points < 0):
        self.points = 0
    else:
        self.points = points

def __str__(self):
    return "The task '" + self.name + "' is worth " + str(self.points) + " and has been completed " + str(self.times_done) + " times."

When it tries constructing it with value -5 (which should set it to 0, via the property), it infinitely recurses on the line self.points = points in the setter function/decoration @points.setter.

Thanks!


Solution

  • Because self.points = ... call the setter; inside the setter, self.points = ... is executed which call the setter; recursion repeated until stack overflow.

    By using other name, you can prevent the recursion: self._points for example.

    Or instead of using self.points = ..., use self.__dict__['points'] = .. (same for getter):

    @property
    def points(self):
        return self.__dict__['points']
    
    @points.setter
    def points(self, points):
        if points < 0:
            self.__dict__['points'] = 0
        else:
            self.__dict__['points'] = points
        # self.__dict__['points'] = max(0, points)