__setattr__,__getattribute__,__getattr__是三个python的与类(class)定义相关的内置函数,与类(class)实例的属性的“赋值”与“调用”有关。
1) 与类属性“赋值”相关
__setattr__: 与类实例的属性的“赋值”操作有关,类实例的任何属性赋值操作都会自动调用该内置函数。该内置函数的默认作用是:将类实例的属性名与对属性的赋值以字典的形式存放在__dict__中,__dict__是python为每个class专门配置的一个字典,用于存储类属性与属性值。
无论一个属性有没有在类中被定义,在为该类实例增加该属性并为该属性赋值时,都会自动调用__setattr__
2) 与类属性“调用”相关
__getattribute__:当调用一个类实例的属性时,无论该属性是否存在,都会自动调用__getattribute__函数。该函数的默认操作是:先查看该类实例的__dict__中是否包含要调用的属性,如果有则返回属性值;如果没有,则发出KeyError或AttributeError信号,然后返回属性值为None.
默认情况下__getattribute__函数不对AttributeError的情况进行处理,此时AttributeError会继续存在,自动触发__getattr__函数,__getattr__中的所有操作是对AttributeError的情况的应对。
如果通过程序员手工修改__getattribute__函数,使__getattribute__拥有了对AttributeError的处理操作,则AttributeError会消失,不再被后传到__getattr__函数,也就不会触发__getattr__的操作。
############################################################################
综上:python在类实例的定义过程中,自动为该类实例分配了一个用于存储类实例属性的字典“__dict__”。
__setattr__:通过向__dict__中添加key与value,设置类实例的属性。不论这个属性有没有在类定义中被定义,都不影响此操作向__dict__中添加key与value。
备注:赋值与调用是两个独立的过程,赋值过程不存在调用,因此不会触发__getattribute__函数。
测试代码如下:
class AboutAttr(object):
def __init__(self,name):
self.name=name
def __setattr__(self,attribute_name,value):
print('触发了__setattr__,被赋值的属性名为:{},赋的值为:{}'.format(attribute_name,value))
# self.__dict__[attribute_name]=value ## 将属性值存放到__dict__中
def __getattribute__(self, attribute_name):
## 函數功能:获取属性值。只要调用属性,该函数就会被调用。 自动先搜索 __dict__,判断属性名是否已存在,
## 然后再选择相应的操作。
print('触发了 __getattribute__,被调用的属性名为:{}'.format(attribute_name))
try:
return super(AboutAttr, self).__getattribute__(attribute_name)
except AttributeError as ex:
print("__getattribute__ 处理了 AttributeError异常")
# return 'AttributeError dealed '
def __getattr__(self, attribute_name):
print('触发了 __getattr__')
return 'default'
if __name__=='__main__':
at = AboutAttr('test')
print('\n操作:at.name')
at.name='hello world'
print('\n操作:at.age')
at.age=100
print('\n操作:at.height')
at.height=180
print("\n#######调用操作#######")
print('\n操作,调用已被定义属性:print(at.name)')
print(at.name)
print('\n操作,调用已被定义属性:print(at.age)')
print(at.age)
print('\n操作,调用已被定义属性::print(at.height)')
print(at.height)
print('\n操作:调用未被定义属性:print(at.not_exist)')
print(at.not_exist)