1

我试图通过使用 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)
4

2 回答 2

3

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

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

通常,在使用这些方法时需要小心,因为它们的调用频率可能比您意识到的要高。如果您的特殊处理仅适用于某些特定属性,您可能希望使用 aproperty来代替。

于 2016-05-10T07:32:59.240 回答
3

__setattr__调用所有属性设置。这包括self.person = Person()调用__init__

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

这将调用self.__setattr__('person', Person()),它反过来尝试访问self.person,然后调用,self.__getattr__('person')因为还没有这样的属性。然后在__getattr__您尝试不断访问时陷入无限循环self.person

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

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应引发 an:

def __getattr__(self,attr):
    print ("Calling the getattr function")
    if attr == 'person':
        raise AttributeError('person')
    return getattr(self.person, attr)
于 2016-05-10T07:33:43.927 回答