属性查找顺序
一般情况下属性访问的默认行为是从对象的字典中获取的;
例如testinstance.name 的查找链为:
testinstance.dict[‘name’] —-> type(testisntance).dict[‘name’] —->** **type(testinstance)
get
一个类中定义了get()、set()、delete()中的任何方法,则这个类的对象称为描述符,更多关于描述符的知识详见python描述符
class M:def __init__(self, x=1):self.x = xdef __get__(self, instance, owner):print("调用__get__方法")return self.xdef __set__(self, instance, value):print("调用__set__方法")self.x = valueclass AA:m = M(x=2)if __name__ == '__main__':a = AA()print(a.m)print('*'*30)a.m = 33print(a.m)------------ ------------#调用__get__方法#2#******************************#调用__set__方法调用__get__方法#33
getattr
一般只在当对象的属性不存在的时候调用,如果正常的可以找到对象属性的话,是不会调用getattr方法的
class B:a = 1def __getattr__(self, item):print("调用__getattr__方法")return itemif __name__ == '__main__':b = B()print(b.a) # 1print(b.aa) # 调用__getattr__方法# aa
getattribute
不管属性存不存在,该方法都会被调用,当类中同时存在getattribute和 getattr时,getattr将不会被调用,假如我们想保留getattr方法的作用,可在getarrtibute方法中返回父类的同名方法
class B:a = 1def __getattribute__(self, item):print("调用__getattribute__方法")return item# 返回父类的同名方法,可保留__getattr__方法的作用# return object.__getattribute__(self, itemdef __getattr__(self, item):print("调用__getattr__方法")return itemif __name__ == '__main__':b = B()print(b.a)print(b.aa)-----------------#调用__getattribute__方法#a#调用__getattribute__方法#aa
getattr()
内置函数,可用来获取对象的属性和方法
class B:a = 1def __getattribute__(self, item):print("调用__getattribute__方法")return object.__getattribute__(self, item)def __getattr__(self, item):print("调用__getattr__方法")return itemdef bb(self):return "实例方法"if __name__ == '__main__':b = B()print(getattr(b, 'a')) # 相当于 b.aprint(getattr(b, 'bb')()) # 相当于b.bbprint(getattr(B, 'a')) # 相当于B.a----------------#调用__getattribute__方法#1#调用__getattribute__方法#实例方法#1
getitem
大致作用同getattribute方法,主要区别在于getitem让类实例可以通过[]获取
class B:a = 1def __getattribute__(self, item):print("调用__getattribute__方法")return object.__getattribute__(self, item)def __getattr__(self, item):print("调用__getattr__方法")return itemdef __getitem__(self, item):print("调用__getitem__")return object.__getattribute__(self, item)def bb(self):return "实例方法"if __name__ == '__main__':b = B()print(b['a']) #1
