python描述符(python2.7)定义详解及应用举例

一: python描述符官方定义

In general, a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol. Those methods are __get__()__set__(), and __delete__(). If any of those methods are defined for an object, it is said to be a descriptor。

概括来讲就是一个对象定义了__get__()、__set__()、__delete__()中的任一方法即为描述符。

二:我们先来了解下每个对象都具备的属性__dict__

字典结构, 存放着对象的所有属性

对象属性的查找顺序为:

  1. 实例属性
  2. 类属性
  3. 父类属性
  4. __getattr__

以上查找顺序请自己验证。

上图可以得出cls_x属性是属于A类的,而不是实例的属性。

三: 下边来看下魔法函数, __get__, __set__, __delete__

方法的原型为:

  1. def __get__(self, obj, objtype)
  2. def __set__(self, obj, val)
  3.  def __delete__(self, obj)

self, obj, objtype 到底指的什么,请看下面程序输出:

程序输出:

从输出中可以看出Mytest实例test在访问属性desc时, 会自动调用Desc的__get__方法:

  • self 即为Desc实例, 也就是MyTest属性desc.
  • obj 即为test, MyTest实例
  • objtype 输出中可以看出是MyTest, 所有的一切都是由其开始的。

到此, 我们可以看到Desc其实就是一个描述符, 换而言之描述符就是一个类, 因为其定义了__get__, __set__, __delete中的任一方法。

四: 揭示描述符的诸多疑点

  1. 为什么访问test的desc属性, 会直接去访问描述符的__get__方法呢?

      从我们博文开始讲的实例查询属性的顺序先访问类的__getattribute__, 如果没有找到, 进一步查找类属性, desc到此找到了!!!

      判断属性 desc为一个描述符,此时,它就会做一些变动了,将 MyTest.x 转化为 desc.__dict__['x'].__get__(obj, MyTest) 来访问了。

    2. 上述实验中desc是MyTest的一个类属性, 那描述符能不能作为实例属性呢?

请看输出结果:

???为什么test实例对象没有desc2呢!, 在访问属性desc2时发现是描述符会将访问__getattribute__转换为MyTest.__dict__('desc2').__get__(test, MyTest), MyTest类是没有desc2类属性的所以发生了异常。

3. 如果实例属性与描述符属性相同, python解释器该如何处理呢?

输出结果为:

理论上讲, test实例对象应该是有desc属性的, 不应该还去调用描述符的__get__方法, 从第二行的实例的__dict__中不难看出并没有desc属性了, 这就说明实例属性与描述符属性同名时会被覆盖掉。

我们再进一步删掉描述符中__set__方法呢, 且看输出结果

实例的desc属性回来了!!!, 所以也就没有再去访问描述符的__get__方法。

这还是属性查找顺序的问题, 一个类,如果只定义了 __get__() 方法,而没有定义 __set__(), __delete__() 方法,则认为是非数据描述符; 反之,则成为数据描述符, 数据描述符的优先级是高于实例属性的。

属性查找顺序的总结如下:

1.__getattribute__(), 无条件调用

2. 数据描述符:由 ① 触发调用 (若人为的重载了该 __getattribute__() 方法,可能会调职无法调用描述符)

3. 实例对象的字典(若与描述符对象同名,会被覆盖哦)

4. 类的字典

5. 非数据描述符

6 父类的字典

7. __getattr__() 方法

五:实际应用举例

试想如果我们创建学生对象, 学生对象的分数属性是0<=score<100, 如何检测属性是否正常?

请看代码示例:

输出结果是什么呢? 请看:

可见实现了我们分数属性赋值范围的检测功能。

此时我们进一步讨论下property到底是个什么东东?能否使用描述符去实现一个类似的property呢?

这样也达到了我们想要的效果, 大家可以发散思维, 多多思考描述符数据结构的用法。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值