我想创建具有属性“名称”和“性别”的类“人类”。我想将“性别”属性的分配限制为仅“男性”或“女性”。为此,我们覆盖了 __ setattr __ (自身,名称,值)。
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:性别只能是“男性”或“女性”)
我无法弄清楚当我通过适当的性别时出了什么问题。
答案 0 :(得分:2)
问题是您的__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)
答案 1 :(得分:0)
Chris Dodd's answer回答了问题。
我想分享一个避免这种陷阱的替代实现:
class Human(object):
ALLOWED_GENDERS = ['male', 'female']
def __init__(self, name=None, gender=None):
self.name = name
self._gender = gender
@property
def gender(self):
return self._gender
@gender.setter
def gender(self, newvalue):
if newvalue not in self.ALLOWED_GENDERS:
raise ValueError('Invalid value for gender: %s. Should be one of %s.' % (newvalue, ", ".join(self.ALLOWED_GENDERS)))
self._gender = newvalue
h = Human()
h.name = 'Sweety'
h.gender = 'female'
print(h.gender)
请注意,setter函数名称应与getter函数名称相同。 否则,您将获得两个属性,一个属性为只读,一个属性为可读写。
有关更多信息,请参见: