34

Here is a test class that I wrote to became familiar with @properties and setter functionality in Python script:

class Test(object):
    def __init__(self, value):
        self.x =  value
    @property
    def x(self):
        return self.x
    @x.setter
    def x(self, value):
        self.x = value

The problems is that when I want to create an object from my class, I face the following error:

>>> t = Test(1)

Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    t = Test(1)
  File "<pyshell#18>", line 3, in __init__
    self.x =  value
  File "<pyshell#18>", line 9, in x
    self.x = value
  File "<pyshell#18>", line 9, in x
  #A bunch of lines skipped
RuntimeError: maximum recursion depth exceeded
>>> 
1
  • 2
    Use self._x instead of self.x for private member. By naming both member and property x property shadows member, and return self.x in getter body calls itself. Commented Apr 29, 2016 at 6:53

2 Answers 2

55

You are using the same name for the getter, setter and attribute. When setting up a property, you must rename the attribute locally; the convention is to prefix it with an underscore.

class Test(object):
    def __init__(self, value):
        self._x =  value

    @property
    def x(self):
        return self._x
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you. Please take a look at Byte Commander's answer here. He used same name for setter, getter and variable, but his program works fine.
If you've defined the setter method, it's better to only access the private variable self._x in the getter / setter / deleter methods. In __init__ you can just say self.x = value.
@Rob I'm not sure that's correct. Why is it better? It's not a convention I'm aware of.
You are implementing a setter methode for a reason, probably to do some input checking / manipulation. It makes sense to do the same thing during instantiation of the object.
Yes, exactly. Assigning to the private attribute in __init__ will bypass the property setter method and therefore not apply the logic contained there, as @Rob said. It is probably buggy or at least inconsistent to allow potentially different values during instantiation and later one, during re-assignment.
-3

The problem is in these lines:

def x(self):
    return self.x

Replace it with

def get_x(self):
    return self.x

Because now the function calls itself, leading to the recursion depth exceeded.

2 Comments

I want to use @properties.
Using getters/setters is a Python antipattern. It's recommended to uses properties with the @property decorator. Read: pythonmorsels.com/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.