递归错误:超过最大递归深度 Python 属性 getter 和 setter。

4

我正在尝试在这个简单的类中实现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


3个回答

2
似乎由于name是一个属性,并且在定义时使用了get_nameset_name,因此当您调用self.name = n时,它实际上调用的是属性的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)

1
首选答案是详细解释。 - indianwebdevil

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

0

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

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方法中,您一遍又一遍地调用setter方法,并使用self._name = n来防止Python进入无限循环。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接