3

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

2 回答 2

7

问题是在Manager.__init__,你调用__setattr__来设置属性person。但在 中__setattr__,您假设self.person已经设置并具有良好定义的__dict__. 实际上,它还没有被设置,所以你最终调用__getattr__which 调用它自己永远试图 get self.person

一种可能的解决方法是绕过对__setattr__in的初始调用Manager.__init__

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

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

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

于 2013-12-03T20:53:05.113 回答
2

mgilson 的答案几乎是正确的,但是,在__setattr__类管理器的功能中,中间缺少一个点person__dict__

def __setattr__(self,attr, value):
        print "calling setattr"
        self.person__dict__["attr"]=value

__init__尝试设置 self.person 时,__setattr__查询一个不存在的属性person__dict__,经理的__getattr__函数被调用。它反过来查询self.person,在这个阶段不存在,在这个阶段你得到一个__getattr__递归。

于 2016-11-21T20:58:28.817 回答