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

2024-06-08 06:39:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有下面的代码,它包含一个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()

Tags: nameselfreturnobjectdefmanagerpayperson
2条回答

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

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

__init__试图设置自己人,则__setattr__查询不存在的属性person__dict__,管理器的__getattr__函数将被调用。它反过来查询自己人,它在这个阶段不存在,在这个阶段,您将得到一个__getattr__递归。在

问题是在Manager.__init__中,调用__setattr__来设置属性person。但是在__setattr__中,您假设self.person已经被设置并且有一个定义良好的__dict__。实际上,它还没有被设置,所以你最后调用了__getattr__,它永远地调用自己,试图得到self.person。在

这里一个可能的修复方法是绕过对Manager.__init____setattr__的初始调用:

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

这应该避免对“__getattr__('person')”的调用,因为self.person已经设置好了,正常的属性查找可以工作1。在

1__getattr__只有在正常属性查找失败时才会调用

相关问题 更多 >

    热门问题