我有以下代码,其中包含一个人员类和一个委托(delegate)给人员类的管理器类。我正在使用 new style object
(派生自 object
)并运行 python 2.7。
我得到了我无法理解的最大递归深度。我知道使用 setattr 时会出现问题(当我在管理器类中对此进行评论时,我发现它工作正常)。
为什么会发生这种递归以及如何避免它。
class Person(object):
def __init__(self,name,job=None, pay=0):
self.name=name
self.job=job
self.pay=pay
def lastName(self):
return self.name.split()[-1]
def giveraise(self,percent):
self.pay=int(self.pay*(1+percent))
def __str__(self):
return '[Person: %s, %s]' %(self.name, self.pay)
class Manager(object):
def __init__(self,name,pay):
self.person=Person(name,'mgr',pay)
def giveraise(self, percent, bonus=0.10):
self.person.giveraise(percent+bonus)
def __getattr__(self,attr):
print "calling getattr"
return getattr(self.person, attr)
def __setattr__(self,attr, value):
print "calling setattr"
self.person__dict__["attr"]=value
def __str__(self):
return str(self.person)
if __name__=="__main__":
sue = Person("sue Jones","dev",10000)
sue.giveraise(0.10)
print sue
print sue.lastName()
print "- -"*25
tom = Manager("Tom mandy", 50000)
tom.giveraise(.10)
print tom
print tom.lastName()
最佳答案
问题在于,在 Manager.__init__
中,您调用 __setattr__
来设置属性 person
。但是在 __setattr__
中,您假设 self.person
已经设置并且具有定义良好的 __dict__
。实际上,它还没有被设置,所以你最终调用了 __getattr__
,它会永远调用自己来尝试获取 self.person
。
这里一个可能的解决方法是绕过 Manager.__init__
中对 __setattr__
的初始调用:
class Manager(object):
def __init__(self,name,pay):
self.__dict__['person']=Person(name,'mgr',pay)
这应该避免调用“__getattr__('person')
”,因为 self.person
已经被设置并且正常的属性查找将起作用1.
1__getattr__
仅在正常属性查找失败时调用
关于python - 在 python 新样式对象中使用 __setattr__ 时的最大递归深度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20361340/