在Python中,当你访问对象的一个属性(也就是写出类似obj.xxx的代码时),访问的优先级从高到低如下所示:
1.getattribute
这是优先级最高的函数,所有对属性的访问必先访问它。举个例子:
class Obj(object):
def __init__(self, weight, price):
self.weight = weight
self.price = price
def __getattribute__(self, name):
print name
return 2
obj = Obj(1,2)
print obj.__getattribute__
print obj.weight
得到的输出为:
__getattribute__
2
weight
2
可以看到,哪怕是访问__getattribute__本身也要先经过__getattribute__函数
2.覆盖型描述符
非覆盖型描述符又称为数据描述符,也就是定义了__get__和__set__的描述符。
描述符的具体语法可以参见这篇文章:https://www.cnblogs.com/wickedpriest/p/11913593.html
需要注意的是,当用户自己定义了__getattribute__时,对数据描述符的访问可能会被忽略。
3.实例属性、4.类属性、5.非覆盖型描述符
这几个比较简单,不再赘述
6.父类的属性
注意是父类的属性,而不是父类对象的属性。父类中定义的属性也是子类的属性
7.getattr
怎么找都找不到该属性了,才会调用__getattr__来访问。
以下代码在返回值和注释中标明了访问顺序:
class Quantity1(object):
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
return 2
def __set__(self, instance, val):
pass
class Quantity2(object):
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
return 5
class A(object):
val = 6 # 6 父类属性
def __init__(self):
self.val = 3 # 3 实例属性
class B(A):
val = 4 # 4 类属性
val = Quantity2("val") # 5 非覆盖型描述符
val = Quantity1("val") # 2 覆盖型描述符
def __init__(self):
super(B, self).__init__()
self.val = 3 # 3 实例属性
def __getattr__(self, name): # 7 __getattr__
return 7
def __getattribute__(self, name): # 1 __getattribute__
return 1