4

I am trying to do getter setter in this simple class,

class Person:

    def __init__(self, n):
        self.name = n

    def get_name(self):
        return self.name

    def set_name(self, n):
        self.name = n

    name = property(get_name, set_name)


p = Person('Lewis')
p.name = 'Philo'

Looks pretty simple and straightforward, but somehow it's not working, what am I missing, help me find what is the understanding that I am going wrong.

I get the following error.

Traceback (most recent call last):
  File "/Users/napoleon/python-play/oops/person.py", line 15, in <module>
    p = Person('Lewis')
  File "/Users/napoleon/python-play/oops/person.py", line 4, in __init__
    self.name = n
  File "/Users/napoleon/python-play/oops/person.py", line 10, in set_name
    self.name = n
  File "/Users/napoleon/python-play/oops/person.py", line 10, in set_name
    self.name = n
  File "/Users/napoleon/python-play/oops/person.py", line 10, in set_name
    self.name = n
  [Previous line repeated 994 more times]
RecursionError: maximum recursion depth exceeded

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
indianwebdevil
  • 4,879
  • 7
  • 37
  • 51
  • A more accurate duplicate: [Using Properties in Python classes cause “maximum recursion depth exceeded” (duplicate)](https://stackoverflow.com/q/36931415/6045800) – Tomerikoo Aug 11 '21 at 09:14

3 Answers3

2

seems like since name is a property, that you defined with get_name and set_name when you call self.name = n what it does is actually calls the setter of the property, which is set_name.

when you initialize the Person object, it calls __init__ which then calls set_name since it has the line self.name = n, and the same happens in set_name itself (since it has the same line).

a solution may be creating a _name member and using it in the getter and setter.

in more complex cases you may check if it's not holding the value you sent to the setter, and only then change the member's value in the setter.

class Person:
    _name = None
    def __init__(self, n):
        self._name = n

    def get_name(self):
        return self._name

    def set_name(self, n):
        self._name = n

    name = property(get_name, set_name)
Daniel
  • 1,895
  • 9
  • 20
1

Whenever you are making accessors and mutators in Python, you shouldn't use the same tag for the property and attributes, so all you need to do is use the _ to prevent the infinite loop:

Just replace self.name with self._name and you should be good:

class Person:
    def __init__(self, n):
        self.name = n

    def get_name(self):
        return self._name

    def set_name(self, n):
        self._name = n

    name = property(get_name, set_name)

    p = Person('Lewis')
    p.name = 'Philo'
    
    print(p.get_name()) #prints "Philo"
milanbalazs
  • 4,811
  • 4
  • 23
  • 45
Aniketh Malyala
  • 2,650
  • 1
  • 5
  • 14
0

That's because the code in your class is running an infinite loop.

class Person:

    def __init__(self, n):
        self.name = n

    def get_name(self):
        return self.name

    def set_name(self, n):
        self.name = n

    name = property(get_name, set_name)


p = Person('Lewis')
p.name = 'Philo'

should be:

class Person:

    def __init__(self, n):
        self.name = n

    def get_name(self):
        return self._name

    def set_name(self, n):
        self._name = n

    name = property(get_name, set_name)


p = Person('Lewis')
p.name = 'Philo'

The extra _ is so that you don't run an infinite loop. See, whenever you set or get the name with your code you provided, it would run the set_name or get_name forever because you are either setting or getting the name within the getter or setter methods.

For example, with p.name = 'Philo', you are running the setter method. Within the setter method, though, you are calling the setter method again and again with self.name = n, and doing self._name = n prevents Python from an infinite loop.

Daniyal Warraich
  • 446
  • 3
  • 13