在python新样式对象中使用__setattr__时的最大递归深度?

bra*_*orm 1 python class object setattr getattr

我有以下代码,其中包含一个person类和一个委托给person类的Manager类.我正在使用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()
Run Code Online (Sandbox Code Playgroud)

mgi*_*son 7

问题在于Manager.__init__,您调用__setattr__设置属性person.但是__setattr__,你认为self.person已经设定并且定义明确__dict__.实际上,它尚未设置,所以你最终会调用__getattr__哪些调用自己永远试图获得self.person.

这里可能的一个解决方法是绕过初始调用__setattr__in Manager.__init__:

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

这应该避免调用" __getattr__('person')"因为self.person已经设置并且正常的属性查找将起作用1.

__getattr__仅在正常属性查找失败时才调用1