我试图通过使用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)
答案 0 :(得分: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
:
def __getattr__(self,attr):
print ("Calling the getattr function")
if attr == 'person':
raise AttributeError('person')
return getattr(self.person, attr)
答案 1 :(得分:1)
在您的实例完全初始化之前,__setattr__
和__getattr__
也适用。在这种情况下,您的第self.person = Person()
行会调用__setattr__
。然后调用__getattr__
(因为self.person
尚未定义),然后再次递归调用__getattr__
(出于同样的原因)。
有几种方法可以解决这个问题。也许最简单的方法是通过执行__setattr__
来绕过对self.person
初始super().__setattr__('person', Person())
调用的property
调用。
通常,在使用这些方法时需要小心,因为它们可能比您意识到的更频繁地被调用。如果您的特殊处理仅适用于少数特定属性,则可能需要使用{{1}}。