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

在python新样式对象中使用_setattr__时的最大递归深度?,python,class,object,getattr,setattr,Python,Class,Object,Getattr,Setattr,我有下面的代码,它由person类和委托给person类的Manager类组成。我正在使用新样式对象(源自对象)并运行python 2.7。 我得到了我无法理解的最大递归深度。我知道当使用setattr时会出现问题(当我在manager类中注释掉这一点时,我发现它工作得很好)。 为什么会发生这种递归以及如何避免它 class Person(object): def __init__(self,name,job=None, pay=0): self.name=name

我有下面的代码,它由person类和委托给person类的Manager类组成。我正在使用
新样式对象
(源自
对象
)并运行python 2.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()

问题在于,在
管理器中,您可以调用
设置属性
人员
。但是在
\uuuu setattr\uuuuuu
中,您假定已设置了
self.person
,并且有一个定义良好的
\uuuuuu dict
。事实上,它还没有被设置,所以你最终调用了
\uuu getattr\uuuu
,它一直在调用自己,试图获取
self.person

这里一个可能的修复方法是绕过对
管理器中
\uuuuu setattr\uuuuu
的初始调用

class Manager(object):
    def __init__(self,name,pay):
        self.__dict__['person']=Person(name,'mgr',pay)
def __setattr__(self,attr, value):
        print "calling setattr"
        self.person__dict__["attr"]=value
这应该避免调用“
\uuu getattr\uuuu('person')
”,因为
self.person
将已经设置,并且正常的属性查找将工作1


1
\uuuuu getattr\uuuuuu
仅在正常属性查找失败时调用

mgilson的答案几乎是正确的,但是,在类管理器的
\uuuuuu setattr\uuuuuuuu
函数中,在
person\uuu dict\uuuuuuu
之间缺少一个点:

class Manager(object):
    def __init__(self,name,pay):
        self.__dict__['person']=Person(name,'mgr',pay)
def __setattr__(self,attr, value):
        print "calling setattr"
        self.person__dict__["attr"]=value
\uuuuu init\uuuuuuu
尝试设置self.person时,
\uuuuuu setattr\uuuuuu
查询一个不存在的属性
person\uuuuu dict\uuuuuuu
,将调用管理者的
\uuuuu getattr\uuuuuu
函数。它反过来查询self.person,而self.person在此阶段不存在,在此阶段您将得到一个
\uuuu getattr\uuuu
递归。

我将setattr改为:
def\uu setattr\uuuuu(self,attr,value):打印“calling setattr”返回setattr(self.person,attr,value)
,但我仍然得到最大递归深度。为什么我得到这个递归深度问题。你的解决方案很好。但我想了解为什么最大递归深度occurs@user1988876--问题是因为在这一点上,
self.person
还不存在。(从未设置过)。因此,这会强制调用
\uuu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,它不应该返回
none
或其他什么吗similar@user1988876--因为
\uu getattr\uu
中有一行
self.person
。如果通过正常方法找不到属性,则调用
\uuuu getattr\uuuuu
(再次!)。此处未隐式返回
None
。你为什么期望会有这样的结果?