RecursionError:最大递归深度超出了python属性getter setter [重复]

Posted

技术标签:

【中文标题】RecursionError:最大递归深度超出了python属性getter setter [重复]【英文标题】:RecursionError: maximum recursion depth exceeded python property getter setter [duplicate] 【发布时间】:2021-10-14 13:44:44 【问题描述】:

我正在尝试在这个简单的类中做 getter setter,

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'

看起来非常简单明了,但不知何故它不起作用,我错过了什么,帮助我找到我出错的理解。

我收到以下错误。

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

【问题讨论】:

更准确的副本:Using Properties in Python classes cause “maximum recursion depth exceeded” (duplicate) 【参考方案1】:

似乎因为name 是一个属性,当您调用self.name = n 时使用get_nameset_name 定义它实际上是调用属性的设置器,即set_name

当您初始化 Person 对象时,它会调用 __init__,然后调用 set_name,因为它有 self.name = n 行,同样的情况发生在 set_name 本身(因为它有相同的行)。

一个解决方案可能是创建一个_name 成员并在getter 和setter 中使用它。

在更复杂的情况下,您可以检查它是否没有保存您发送给 setter 的值,然后才在 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)

【讨论】:

answer 是首选的详细解释。【参考方案2】:

当你在 Python 中创建访问器和修改器时,你不应该对属性和属性使用相同的标签,所以你需要做的就是使用 _ 来防止无限循环:

只需将self.name 替换为self._name 就可以了:

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"

【讨论】:

【参考方案3】:

那是因为你的类中的代码正在运行一个无限循环。

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'

应该是:

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'

额外的_ 是为了让您不会运行无限循环。请注意,每当您使用提供的代码设置或获取名称时,它将永远运行 set_nameget_name,因为您在 getter 或 setter 方法中设置或获取名称。

例如,使用p.name = 'Philo',您正在运行setter 方法。但是,在 setter 方法中,您使用 self.name = n 一次又一次地调用 setter 方法,而使用 self._name = n 可以防止 Python 陷入无限循环。

【讨论】:

以上是关于RecursionError:最大递归深度超出了python属性getter setter [重复]的主要内容,如果未能解决你的问题,请参考以下文章

RecursionError:最大递归深度超出了python属性getter setter [重复]

RecursionError:重命名列条目后调用 Python 对象时超出最大递归深度

Celery 4.2-Django RecursionError:超出最大递归深度

Pyinstaller 超出最大递归深度

“超出最大递归深度”,试图调用重载函数

RecursionError:比较中超出了最大递归深度'