繁体   English   中英

Python中的__setattr__函数

[英]__setattr__ function in Python

我试图通过使用getattr和setattr函数来理解Python中委托的概念。 基本思想是首先通过Professional类在Person类中设置属性'lang'的值,然后再检索该值。 问题在于结果是无限循环。

class Person:
    def __init__(self,name='Subhayan',job='Engineer',unique='Unique'):
        print ("Inside init function of Person")
        self.name = name
        self.job = job
        self.salary = 50000
        self.lang = "Perl"

    def __setattr__(self,att,value):
        self.__dict__[att] = value


class Professional:
    job = 'Engineer'
    salary = 75000
    def __init__(self):
        print ("Inside Professional init function")
        self.person = Person()

    def __getattr__(self,attr):
        print ("Calling the getattr function")
        return getattr(self.person, attr)

    def __setattr__(self,att,value):
        # print ("calling the setattr function setting the value of %s to %s" %(attr,value))
        self.person.__setattr__(self,att,value)


if __name__ == '__main__':
    print ("Calling the script as main")
    Prof = Professional()
    print ("Salary is",Prof.salary)
    print ("name is",Prof.__class__)
    print ("Setting the value of lang")
    Prof.lang = 'Python'
    value = Prof.lang
    print ("The value of lang is ;",value)

所有属性设置将调用__setattr__ 这包括__init__self.person = Person()调用:

def __init__(self):
    print ("Inside Professional init function")
    self.person = Person()

这将称为self.__setattr__('person', Person()) ,后者继而尝试访问self.person ,然后再调用self.__getattr__('person')因为尚无此属性。 然后在__getattr__中,当您尝试不断访问self.person ,您将self.person无限循环。

您可以在__setattr__测试特定的person属性(并将其委派给基本实现):

def __setattr__(self, att, value):
    # print ("calling the setattr function setting the value of %s to %s" %(attr,value))
    if att == 'person':
        return super().__setattr__(att, value)
    return self.person.__setattr__(self,att,value)

您可能还想在__getattr__添加测试; 如果使用person调用,则该属性尚未设置,应引发AttributeError

def __getattr__(self,attr):
    print ("Calling the getattr function")
    if attr == 'person':
        raise AttributeError('person')
    return getattr(self.person, attr)

实例完全初始化之前, __getattr__ __setattr____getattr__也适用。 在这种情况下,您的一行self.person = Person()调用__setattr__ 然后调用__getattr__ (因为self.person尚未定义),然后再递归调用__getattr__ (出于相同的原因)。

有几种解决方法。 也许最简单的方法是通过执行例如super().__setattr__('person', Person())来规避对初始self.person分配的__setattr__调用。

通常,使用这些方法时需要小心,因为调用它们的次数可能比您想像的要多。 如果特殊处理仅适用于某些特定属性,则可能需要使用property

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM