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

标签 python class object getattr setattr

我有以下代码,其中包含一个人员类和一个委托(delegate)给人员类的管理器类。我正在使用 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()

最佳答案

问题在于,在 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__ 仅在正常属性查找失败时调用

关于python - 在 python 新样式对象中使用 __setattr__ 时的最大递归深度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20361340/

相关文章:

python - 在 Ubuntu 上卸载了 IPython,但仍然可以使用

python - 在一个模板中格式化任意可迭代对象

c++ - std 命名空间中变量/类的前向声明

class - 参数化类和多态性

javascript - 如何将数组中的元素分组为满足特定条件的对象并将其推送到新数组

python - Itertools 相当于嵌套循环 "for x in xs: for y in ys..."

python - 我想使用 python-social-auth 通过 vk.com 进行授权,并通过重定向 uri 获得错误

jquery - 使用 jQuery 添加和删除类

javascript - 如何基于对象键/值配对创建有序列表?

javascript - 在对象数组中添加匹配键的值