属性描述符的介绍
- 它是一个强大的通用协议
- 它是
properties, methods, static methods, class methods 和super()
的调用原理 - 它是针对某一个类的而言的
属性描述符作用
- 属性描述符的作用与
@property装饰器
的作用相同,可以实现在形式上是属性访问,但是实际上却是内部调用方法 - 不同点:
@property装饰器
的复用性很差,当我们有两个属性需要使用同样的方法来获取或设置值时,需要定义两个@property装饰器
才可以,复用性极差,而属性描述符直接调用即可实现!!
属性描述符协议
- 属性描述符就是实现了特定协议的类,只要实现了
__get__,__set__和__del__
三个方法中的任意一个,这个类就是某个类的属性描述符
- 它能实现对多个属性相同的
设置数据、获取数据
逻辑的一种方式,简单来说就是:创建一个实例,作为另一个类的类属性
代码解释
- 定义一个IntField类为描述符类
- 创建IntField类的实例,作为另一个User类的属性来实现某种逻辑
class InterFiled(object):
def __set__(self, instance, value):
pass
def __get__(self, instance, owner):
pass
def __del__(self):
pass
class User(object):
age = InterFiled()
ycx = User()
ycx.age = 18
print(ycx.age)
del ycx.age
- 上述就是,属性描述符的原型,具体的业务逻辑,需要你在
__get__,__set__和__del__
中实现
注意
- 如果一个对象同时定义了
__get__和__set__
方法,它被称做数据描述符(data descriptor)。 - 只定义
__get__
方法的对象则被称为非数据描述符(non-data descriptor)
实现需求
- 定义一个属性描述符类,再定义一个User类,实现User类中的age属性,如果age的值为int类型,则将age的值设置为此值,否则抛出异常!!
- 代码实现:
class InterFiled(object):
def __set__(self, instance, value):
if not isinstance(value, int):
raise TypeError('Type Error')
self.val = value
def __get__(self, instance, owner):
return self.val
def __del__(self):
pass
class User(object):
age = InterFiled()
ycx = User()
ycx.age = 18
print(ycx.age)
- console输出:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ec4c89ba42f200f961b23abb911fb130.png)
- 上述已经实现了User类中的age属性的先判断后设置值
- 当我们还需要某个属性的判断方法与age属性的判断方法相同时,直接调用属性描述符即可!!
调用顺序
当为数据描述符时, __get__优先级高于__dict__
当为非数据描述符时,__dict__优先级高于__get__