八叶一刀·无仞剑

万物流转,无中生有,有归于无

导航

Python属性的查询优先级

Posted on 2019-12-04 19:23  闪之剑圣  阅读(586)  评论(0编辑  收藏  举报

在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