Python属性以及属性符简介

属性描述符和属性查找过程

属性描述符是一个类,只需实现下面方法中的一种该类就可以被称之为属性描述符

1 class Person:
2     def __get__(self, instance, owner):
3         pass
4         
5     def __set__(self, instance, value):
6         pass
7         
8     def __delete__(self, instance):
9         pass

只需实现上面三个魔法函数的一种就可以称该类为属性描述符

property类实现了完整的描述符协议,通常可以只实现部分协议,

描述符的作用是:创建一个实例,作为另一个类的类属性

  在下面的代码实例中,IntField是一个属性描述符,因为它都实现了这三种魔法方法,然后定义一个User类,里面的类变量是IntField属性描述符对象,当定义u.a = 30时,会调用__set__方法,从下面的图片中可以看到,self就是属性描述符对象,instance是User对象,value就是所附的值,这个有一种应用:就是判断输入的属性值是不是满足要求,可以用属性描述符来判断,在__set__函数里面加上判断,

 1 class IntField:
 2     def __get__(self, instance, owner):
 3         pass
 4 
 5     def __set__(self, instance, value):
 6         pass
 7 
 8     def __delete__(self, instance):
 9         pass
10 
11 
12 class User:
13     a = IntField()
14 
15 
16 if __name__ == "__main__":
17     u = User()
18     u.a = 30

 下面的例子就是用__set__做判断用户的输入

 1 import numbers
 2 
 3 
 4 class IntField:
 5     def __get__(self, instance, owner):
 6         pass
 7 
 8     def __set__(self, instance, value):
 9         if not isinstance(value, numbers.Integral):
10             raise ValueError("Int value need")
11         else:
12             self.value = value
13 
14     def __delete__(self, instance):
15         pass
16 
17 
18 class User:
19     a = IntField()
20 
21 
22 if __name__ == "__main__":
23     u = User()
24     u.a = "abc"

从上面代码可以看出,现在赋值u.a = "abc",输出如下,可以看到功能成功实现。

 1 import numbers
 2 
 3 
 4 class IntField:
 5     def __get__(self, instance, owner):
 6         return 40
 7 
 8     def __set__(self, instance, value):
 9         if not isinstance(value, numbers.Integral):
10             raise ValueError("Int value need")
11         else:
12             self.value = value
13 
14     def __delete__(self, instance):
15         pass
16 
17 
18 class User:
19     a = IntField()
20 
21 
22 if __name__ == "__main__":
23     u = User()
24     u.a = 30
25     print(u.a)

当想要获取对象的属性(属性描述符对象)的值时,它会调用__get__方法,如上所示,__get__方法返回的是40,当获取u.a的值时,会调用__get__方法返回40

数据属性描述符:实现__get__和__set__方法

非数据属性描述符:只实现__get__方法

 如果user是User类的实例,那么user.age(以及等价的getattr(user, 'age'))

首先调用__getattribute__,如果类定义了__getattr__方法,那么在__getattribute__抛出AttributeError的时候就会调用__getattr__,而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。

user = User(), 那么user.age顺序如下:

(1) 如果"age"是出现在User或其基类的__dict__中,且age是data descriptor(数据属性描述符), 那么调用其__get__方法,

(2) 如果"age"出现在user(obj)对象的__dict__中,那么直接返回obj.__dict__['age'],否则

(3)如果"age"出现在User或其基类__dict__中

(3.1) 如果age是non-data descriptor(非数据属性描述符),那么调用其__get__方法,否则

(3.2)返回__dict__['age']

(4) 如果User有__getattr__方法,调用__getattr__方法,否则

(5)抛出AttributeError

原文地址:https://www.cnblogs.com/xiebinbbb/p/13722970.html