【7.3】属性描述符和属性查找过程
属性描述符—利用的是抽象的方法, 把十几个字段共同的特性抽出来,每个字段都用这个特性,达到节省代码的目的。
属性描述符,有数据属性描述符和非数据属性描述符
__get__
__set__
__delete__
实现上述三个魔法函数其中之一即可成为属性描述符,如果只实现__get__称之为非数据属性描述符,只有同时实现__get__和__set__才称之为数据属性描述符
1 #!/user/bin/env python
2 # -*- coding:utf-8 -*-
3 import numbers
4
5
6 class IntField:
7 def __get__(self, instance, owner):
8 return self.value
9
10 def __set__(self, instance, value):
11 if not isinstance(value, numbers.Integral):
12 raise ValueError('int value need')
13 if value < 0:
14 raise ValueError('positive value need')
15 self.value = value
16
17 def __delete__(self, instance):
18 pass
19
20
21 class User:
22 age = IntField()
23
24
25 if __name__ == '__main__':
26 user = User()
27 user.age = 30
28 print(user.age)
29
30 # ValueError('int value need')
31 # user.age = 'z'
32 # print(user.age)
33
34 # ValueError('positive value need')
35 # user.age = -1
36 # print(user.age)
30
总结一下:
1.需要把校验放在一个类里面(IntField)
2.需要重写魔法函数
3.age = IntField()
4.给age赋值的时候,会调用IntField里面的__get__方法
属性查找过程
如果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的__dict__中(对象属性), 那么直接返回 obj.__dict__[‘age’], 否则 —>如果age不是类属性或者User不是数据属性描述符,则去对象属性中查找age
(3)如果“age”出现在User或其基类的__dict__中(类属性)
(3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
(3.2)返回 class.__dict__[‘age’]
(4)如果User有__getattr__方法,调用__getattr__方法,否则 —>对象属性和类属性中都没有age,则调用User类的__getattr__方法
(5)抛出AttributeError
(3.1)
1 #!/user/bin/env python
2 # -*- coding:utf-8 -*-
3 import numbers
4
5
6 class IntField:
7 def __get__(self, instance, owner):
8 return self.value
9
10 def __set__(self, instance, value):
11 if not isinstance(value, numbers.Integral):
12 raise ValueError('int value need')
13 if value < 0:
14 raise ValueError('positive value need')
15 self.value = value
16
17 def __delete__(self, instance):
18 pass
19
20
21 class NotDataIntField:
22 def __get__(self, instance, owner):
23 return self.value
24
25
26 class User:
27 age = NotDataIntField()
28
29
30 if __name__ == '__main__':
31 user = User()
32 User.age = 30
33 User.z = 10
34 print(User.__dict__)
35 print(user.__dict__)
36 print(User.age)
37 print(user.age)
38
39 # ValueError('int value need')
40 # user.age = 'z'
41 # print(user.age)
42
43 # ValueError('positive value need')
44 # user.age = -1
45 # print(user.age)
{'__module__': '__main__', 'age': 30, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None, 'z': 10}
{}
30
30
转载于//www.cnblogs.com/zydeboke/p/11265485.html
还没有评论,来说两句吧...