Exception 重写_setattr时的无限递归__

Exception 重写_setattr时的无限递归__,exception,recursion,python-3.6,setattr,Exception,Recursion,Python 3.6,Setattr,我想创建属性为“name”和“gender”的类“Human”。我想将“性别”属性的赋值限制为仅“男性”或“女性”。为此,我们已重写了\uuuuu setattr\uuuu(self、name、value) 但我得到了以下例外: [Previous line repeated 328 more times] File "/Users/admin/algorithms/betright_test.py", line 143, in **__setattr__** if name =

我想创建属性为“name”和“gender”的类“Human”。我想将“性别”属性的赋值限制为仅“男性”或“女性”。为此,我们已重写了\uuuuu setattr\uuuu(self、name、value)

但我得到了以下例外:

  [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:性别只能是“男性”或“女性”)


当我通过正确的性别考试时,我不知道出了什么问题

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

super().__setattr__(name, value)
请注意,在示例代码中,如果您试图打印h.name,则会得到一个AttributeError,因为您的
\uuuu setattr\uuuu
函数从未设置该属性。所以你想要的是:

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)

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

super().__setattr__(name, value)
请注意,在示例代码中,如果您试图打印h.name,则会得到一个AttributeError,因为您的
\uuuu setattr\uuuu
函数从未设置该属性。所以你想要的是:

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)
回答了这个问题

我想与大家分享一个可避免此陷阱的替代实现:

类人(对象):
允许的性别=[“男性”,“女性”]
定义初始化(self,name=None,gender=None):
self.name=名称
自我。性别=性别
@财产
性别(自我):
回归自我
@性别设定者
定义性别(自我、新价值):
如果newvalue不在self.ALLOWED\u GENDERS中:
raise VALUERROR('性别的无效值:%s。应为%s.%之一(新值,,。。加入(self.ALLOWED_GENDERS)))
self.\u性别=新值
h=人()
h、 name='Sweety'
h、 性别=‘女性’
印刷品(h.性别)
请注意,setter函数名应该与getter函数名相同。 否则,您将得到两个属性,一个是只读的,另一个是可读写的

有关更多信息,请参阅:

    • 回答了这个问题

      我想与大家分享一个可避免此陷阱的替代实现:

      类人(对象):
      允许的性别=[“男性”,“女性”]
      定义初始化(self,name=None,gender=None):
      self.name=名称
      自我。性别=性别
      @财产
      性别(自我):
      回归自我
      @性别设定者
      定义性别(自我、新价值):
      如果newvalue不在self.ALLOWED\u GENDERS中:
      raise VALUERROR('性别的无效值:%s。应为%s.%之一(新值,,。。加入(self.ALLOWED_GENDERS)))
      self.\u性别=新值
      h=人()
      h、 name='Sweety'
      h、 性别=‘女性’
      印刷品(h.性别)
      
      请注意,setter函数名应该与getter函数名相同。 否则,您将得到两个属性,一个是只读的,另一个是可读写的

      有关更多信息,请参阅: