我有下面的代码,它包含一个person类和一个委托给person类的Manager类。我使用new style object
(源于object
)并运行python2.7。
我得到了我无法理解的最大递归深度。我知道在使用setattr时会出现问题(当我在manager类中注释掉它时,我发现它工作得很好)。
为什么会发生这种递归以及如何避免它。在
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()
mgilson的答案几乎是正确的,但是,在类管理器的
__setattr__
函数中,person__dict__
之间缺少一个点:当
__init__
试图设置自己人,则__setattr__
查询不存在的属性person__dict__
,管理器的__getattr__
函数将被调用。它反过来查询自己人,它在这个阶段不存在,在这个阶段,您将得到一个__getattr__
递归。在问题是在
Manager.__init__
中,调用__setattr__
来设置属性person
。但是在__setattr__
中,您假设self.person
已经被设置并且有一个定义良好的__dict__
。实际上,它还没有被设置,所以你最后调用了__getattr__
,它永远地调用自己,试图得到self.person
。在这里一个可能的修复方法是绕过对
Manager.__init__
中__setattr__
的初始调用:这应该避免对“
__getattr__('person')
”的调用,因为self.person
已经设置好了,正常的属性查找可以工作1。在1
__getattr__
只有在正常属性查找失败时才会调用相关问题 更多 >
编程相关推荐