[英]__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.