首页 > 解决方案 > 覆盖 __setattr__ 时的无限递归

问题描述

我想创建具有“名称”和“性别”属性的“人类”类。我想将“性别”属性的分配限制为“男性”或“女性”。为此,我们重写了 __setattr__ (self, name, value)。

class Human(object):
    def __setattr__(self, name, value):
        if name == 'gender':
            if value in ('male', 'female'):
                self.gender = value
            else:
                raise AttributeError('Gender can only be "male" or "female"')


h = Human()
h.name = 'Sweety'
h.gender = 'female'
print(h.gender)

但我得到以下例外:

  [Previous line repeated 328 more times]
  File "/Users/admin/algorithms/betright_test.py", line 143, in **__setattr__**
    if name == 'gender':
RecursionError: maximum recursion depth exceeded in comparison

但是如果我传递了错误的性别(h.gender = 'f'),它会给我正确的错误(AttributeError:性别只能是“男性”或“女性”)

当我通过正确的性别时,我无法弄清楚出了什么问题。

标签: exceptionrecursionpython-3.6setattr

解决方案


问题是您的__setattr__函数包含在无限循环self.gender =中调用的 ...行。__setattr__您需要使用超类方法存储属性而不递归调用:__setattr__

super().__setattr__(name, value)

另请注意,在您的示例代码中,如果您尝试打印 h.name,您会得到一个 AttributeError,因为您的__setattr__函数从未设置该属性。所以你想要的是这样的:

def __setattr__(self, name, value):
    if name == 'gender':
        if value not in ('male', 'female'):
            raise AttributeError('Gender can only be "male" or "female"')
    super().__setattr__(name, value)

推荐阅读