This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: RecursionError when using property() inside classes
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.11, Python 3.10, Python 3.9, Python 3.8, Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: prasechen, steven.daprano
Priority: normal Keywords:

Created on 2022-02-17 12:48 by prasechen, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (3)
msg413403 - (view) Author: chen-y0y0 (prasechen) Date: 2022-02-17 12:48
A simple class definition:
class Foo: bar = property(lambda self: self.bar)
And get the value of Foo.bar, it returns correctly, <property object at 0x**********>.
And get the value of Foo().bar, it raises RecursionError:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
  File "<stdin>", line 1, in <lambda>
  File "<stdin>", line 1, in <lambda>
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
msg413406 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2022-02-17 13:13
This is not a bug, Python is working correctly here. The interpreter is doing exactly what you told it to do, and then raising a RecursionError before you can crash the system.


You have a property instance.bar which returns instance.bar, which returns instance.bar, which returns instance.bar... forever, or until RecursionError is triggered.

Your class is the same as:

class Foo:
    @property
    def bar(self):
        return self.bar

So when you call instance.bar, it looks up bar, which is the property, which looks up bar, which is the property, which looks up bar, and so on.

What did you expect to happen?
msg413407 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2022-02-17 13:18
Maybe you expected to do this:

class C:
    def __init__(self):
        self._value = 999

    @property
    def bar(self):
        return self._value

obj = C()
obj.bar  # returns 999
History
Date User Action Args
2022-04-11 14:59:56adminsetgithub: 90932
2022-02-17 13:18:51steven.dapranosetmessages: + msg413407
2022-02-17 13:13:30steven.dapranosetstatus: open -> closed

nosy: + steven.daprano
messages: + msg413406

resolution: not a bug
stage: resolved
2022-02-17 12:48:24prasechencreate