0

My code:

class MyClass:

    def __init__(self):
        self.value = 0

    def set_value(self, value):
        self.value = 5

    def get_value(self):
        return self.value

    value = property(get_value, set_value)

a = MyClass()

I get the following output:

RecursionError: maximum recursion depth exceeded

My question: Why do I get this output? Why does Python call MyClass.value.__set__ instead of just setting the instance variable to 0?

I mean the property object is a class variable and when initializing the a-instance I do not do anything with the class variable. Hope you know what I mean.

Aliquis
  • 2,091
  • 4
  • 21
  • 40
  • Interesting output, I wouldn't have expected that. Just wanted to add that making `value` a private variable (replacing with `__value`) resolves the problem. – Michael H. Aug 27 '17 at 22:15
  • 1
    @Michael that doesn't make it private, it just name mangles it. As long as the attribute behind the property has a different name (conventionally with a *single* leading underscore, but could be something completely different) there's no recursion. – jonrsharpe Aug 27 '17 at 22:17
  • 1
    It calls `MyClass.value.__set__` because *that's how properties work*. Otherwise you'd just immediately replace the property with a value whenever you assigned to it. – jonrsharpe Aug 27 '17 at 22:18
  • I would have posted an answer here, but can't because the question is closed. I don't think it is an exact duplicate because you are asking about the error. What is going on is that you are introducing an infinite recursion. `__init__` contains `self.value=0` which is interpreted as `self.set_value(0)` which contains `self.value = 5` which is interpreted as `self.set_value(5)` and that method calls into itself again, and again, similarly, introducing an infinite recursion. You need to use a different name for the state variable than the property and `_value` is usually the convention. – Matthew Aug 27 '17 at 22:41

1 Answers1

0

By doing value = property(get_value, set_value) you declare a new descriptor. From now instance.value and instance.value = x will call .get_value() and .set_value().

Danil Speransky
  • 29,891
  • 5
  • 68
  • 79