maximum recursion depth while using __setattr__ in python new style object?

class, getattr, object, python, setattr

Solution

The problem is that in `Manager.__init__`, you call `__setattr__` to set the attribute `person`. But in `__setattr__`, you assume that `self.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 get `self.person`.

One possible fix here is to bypass the initial call to `__setattr__` in `Manager.__init__`:

class Manager(object):
    def __init__(self,name,pay):
        self.__dict__['person']=Person(name,'mgr',pay)

This should avoid the call to "`__getattr__('person')`" since `self.person` will already be set and normal attribute lookup will work1.

1`__getattr__` is only called if normal attribute lookup fails

Problem

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() ```

Original source