递归错误:最大递归深度超过python属性getter setter

2024-05-16 10:52:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我试着在这个简单的课堂上做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


Tags: nameinpyselfplayinitdefline
3条回答

无论何时在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"

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

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出现无限循环

似乎因为name是一个属性,所以在调用get_nameset_name时,您使用get_nameset_name定义了它。它实际上调用了属性的setter,即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)

相关问题 更多 >