I have the following code which comprises of a person class and a Manager class that delegates to a person class. I am using new style object
(derived from object
) and running python 2.7.
I geth maximum recursion depth which I am unable to understand. I know the problem happens when setattr is used (when I commented this out in manager class, I see it works fine).
why this recursion occurs and how to avoid it.
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()
The problem is that in
Manager.__init__
, you call__setattr__
to set the attributeperson
. But in__setattr__
, you assume thatself.person
has already been set and has a well defined__dict__
. In reality, it hasn't been set yet, so you end up calling__getattr__
which calls itself forever trying to getself.person
.One possible fix here is to bypass the initial call to
__setattr__
inManager.__init__
:This should avoid the call to "
__getattr__('person')
" sinceself.person
will already be set and normal attribute lookup will work1.1
__getattr__
is only called if normal attribute lookup fails