描述符

描述符的本质是一个新式类,在这个新式类中,至少实现了__get__()、__set__()、__delete__()中的一个,这也被称为描述符协议

__get__() :调用一个属性时,触发

__set__()  :为一个属性赋值时,触发

__delete__()   :采用del删除属性时,触发

数据描述符:至少实现了__get__()和__set__()

非数据描述符:没有实现__set__() 

 1 class Foo:
 2     a = 4
 3 
 4     def __init__(self):
 5         self.name = 'alex'
 6         self.age = 18
 7 
 8     def __get__(self, instance, owner):
 9         print('=====执行get 方法')
10 
11     def __delete__(self, instance):
12         print('调用dele')
13 
14     def __set__(self, instance, value):
15         print('调用set')
16 
17 
18 class New:
19     x = Foo()
20 
21     def __init__(self, n):
22         self.x = n
23     # def test(self):
24     #     print(self.x.a)
25 
26 
27 n1 = New(10)
28 print(n1.__dict__)
29 输出:
30 调用set
31 {}

相当于New类中的x属性被Foo() 代理了

总结:描述符是在一个类中定义,且只能在类属性中定义,不能再类函数中定义,包括__init__函数(初始化函数)。

 1 class Foo:
 2     a = 4
 3 
 4     def __init__(self):
 5         self.name = 'alex'
 6         self.age = 18
 7 
 8     def __get__(self, instance, owner):
 9         print('=====执行get 方法')
10 
11     def __delete__(self, instance):
12         print('调用dele')
13 
14     def __set__(self, instance, value):
15         print('调用set')
16         instance.__dict__['x'] = value
17 
18 
19 class New:
20     x = Foo()
21 
22     def __init__(self, n):
23         self.x = n
24     # def test(self):
25     #     print(self.x.a)
26 
27 
28 n1 = New(10)
29 # n1.y = 545
30 print(n1.__dict__)
31 输出:
32 调用set
33 {'x': 10}

调用优先级:

1.类属性     2.数据描述符    3.实例属性    4.非数据描述符     5.找不到的属性触发__getatr__()

 1 class Foo:
 2     a = 4
 3 
 4     def __init__(self):
 5         self.name = 'alex'
 6         self.age = 18
 7 
 8     def __get__(self, instance, owner):
 9         print('=====执行get 方法')
10 
11     def __delete__(self, instance):
12         print('调用dele')
13 
14     def __set__(self, instance, value):
15         print('调用set')
16         instance.__dict__['x'] = value
17 
18 
19 class New:
20     x = Foo()
21 
22     # def __init__(self, n):
23     #     self.x = n
24     # def test(self):
25     #     print(self.x.a)
26 
27 
28 print(New.x)   #  从类属性中找,直接触发描述符
29 # New.x = 2   # 按照优先级,先访问类属性,类属性没有,直接创建,不会访问描述符
30 # # print(New.__dict__)
31 # # n1 = New()
32 n1 = New()
33 n1.x = 3   # 描述符大于实例属性
34 n1.x
35 输出:
36 =====执行get 方法
37 None
38 调用set
39 =====执行get 方法

 

posted @ 2020-03-09 23:41  竹石2020  阅读(138)  评论(0编辑  收藏  举报