Python描述符descriptor使用原理解析


Posted in Python onMarch 21, 2020

描述符(descriptor)是实现了__get__、__set__、__del__方法的类,进一步可以细分为两类:

数据描述符:实现了__get__和__set__

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

描述符在类的属性调用中起着很重要的作用,类在调用属性时,遵守两个规则:

按照实例属性、类属性的顺序选择属性,即实例属性优先于类属性

如果在类属性中发现同名的数据描述符,那么该描述符会优先于实例属性

非数据描述符会被实例属性覆盖

class A:
  def __get__(self, obj, cls):
    return f"{obj}: get"
class B:
  value = A()

  def __init__(self):
    self.value = 4
def main():
  g = B()
  print(g.value)
  print(g.__dict__)
if __name__ == "__main__":
  main()

输出结果

4
{'value': 4}

数据描述符优于实例属性

class A:
  def __get__(self, obj, cls):
    return f"{obj}: get"

  def __set__(self, obj, value):
    print(f"{obj}: set, {value}")

class B:
  value = A()

  def __init__(self):
    self.value = 4

def main():
  g = B()
  print(g.value)
  print(g.__dict__)

if __name__ == "__main__":
  main()

输出结果

<__main__.B object at 0x000001165EB85898>: set, 4
<__main__.B object at 0x000001165EB85898>: get
{}

从上述两个例子中可以看到,类B的value属性是一个描述符,当value属性是一个数据描述符时,它屏蔽了实例的同名属性value,实例对value属性的读取与赋值都会直接被转移到类属性value上。

使用描述符实现类的静态方法与类方法

from functools import partial

class Staticmethod:

  def __init__(self, method):
    self.method = method

  def __get__(self, obj, cls):
    return self.method

class Classmethod:

  def __init__(self, method):
    self.method = method
  
  def __get__(self, obj, cls):
    return partial(self.method, cls)

class A:

  @Staticmethod
  def f(self):
    print(f"I'm method f, the value is {self}")
  
  @Classmethod
  def c(self):
    print(f"my class is {self}")
a = A()
a.f(23)
A.f(23)
a.c()
A.c()

输出结果

I'm method f, the value is 23
I'm method f, the value is 23
my class is <class '__main__.A'>
my class is <class '__main__.A'>

静态方法与类方法统一了类属性的两种引用方式。这种统一的过程可以使用描述符修改属性访问的默认方式实现。静态方法限制实例的默认绑定,将方法当做普通函数使用;类方法始终将类作为第一个参数传入,上述的partial将类固定为方法的第一个参数。

总结

  • 描述符是实现了__get__、__set__、__del__等特殊方法的类,在属性访问时起着很大的作用。
  • 数据描述符会覆盖同名的实例属性,通过使用数据描述符,达到通过实例修改类变量的目的。
  • 描述符用于修改属性的默认访问方式,借此可以实现类方法与静态方法。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现html转ubb代码(html2ubb)
Jul 03 Python
让 python 命令行也可以自动补全
Nov 30 Python
Python2.x与Python3.x的区别
Jan 14 Python
Python元组操作实例分析【创建、赋值、更新、删除等】
Jul 24 Python
Python中常见的异常总结
Feb 20 Python
Python使用pymongo模块操作MongoDB的方法示例
Jul 20 Python
python绘制散点图并标记序号的方法
Dec 11 Python
Python3.0 实现决策树算法的流程
Aug 08 Python
Python 中使用 PyMySQL模块操作数据库的方法
Nov 10 Python
pytorch之inception_v3的实现案例
Jan 06 Python
python不同系统中打开方法
Jun 23 Python
python时间time模块处理大全
Oct 25 Python
Python如何省略括号方法详解
Mar 21 #Python
Python如何使用bokeh包和geojson数据绘制地图
Mar 21 #Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
Mar 20 #Python
python+opencv实现移动侦测(帧差法)
Mar 20 #Python
Java Spring项目国际化(i18n)详细方法与实例
Mar 20 #Python
Python 自由定制表格的实现示例
Mar 20 #Python
python实现opencv+scoket网络实时图传
Mar 20 #Python
You might like
PHP伪静态页面函数附使用方法
2008/06/20 PHP
php 静态变量与自定义常量的使用方法
2010/01/26 PHP
PHP图片库imagemagick安装方法
2014/09/23 PHP
PHP面向对象程序设计继承用法简单示例
2018/12/28 PHP
PHP 进程池与轮询调度算法实现多任务的示例代码
2019/11/26 PHP
javascript得到XML某节点的子节点个数的脚本
2008/10/11 Javascript
IE的fireEvent方法概述及应用
2013/02/22 Javascript
使用js+jquery实现无限极联动
2013/05/23 Javascript
从js向Action传中文参数出现乱码问题的解决方法
2013/12/29 Javascript
jQuery插件boxScroll实现图片轮播特效
2015/07/14 Javascript
第二章之Bootstrap 页面排版样式
2016/04/25 Javascript
JavaScript闭包和范围实例详解
2016/12/19 Javascript
详解在vue-cli中使用graphql即vue-apollo的用法
2018/09/08 Javascript
JQuery判断radio单选框是否选中并获取值的方法
2019/01/17 jQuery
基于Taro的微信小程序模板消息-获取formId功能模块封装实践
2019/07/15 Javascript
Vue项目打包部署到iis服务器的配置方法
2019/10/14 Javascript
ES6 proxy和reflect的使用方法与应用实例分析
2020/02/15 Javascript
vue 需求 data中的数据之间的调用操作
2020/08/05 Javascript
[02:26]2016国际邀请赛8月3日开战 中国军团出征西雅图
2016/08/02 DOTA
Python实现获取命令行输出结果的方法
2017/06/10 Python
详谈python3 numpy-loadtxt的编码问题
2018/04/29 Python
OpenCV+Python识别车牌和字符分割的实现
2019/01/31 Python
Python实现图片转字符画的代码实例
2019/02/22 Python
django中ORM模型常用的字段的使用方法
2019/03/05 Python
django的auth认证,authenticate和装饰器功能详解
2019/07/25 Python
Python内置方法和属性应用:反射和单例(推荐)
2020/06/19 Python
Python+Opencv身份证号码区域提取及识别实现
2020/08/25 Python
python在CMD界面读取excel所有数据的示例
2020/09/28 Python
python基于pygame实现飞机大作战小游戏
2020/11/19 Python
python 数据类型强制转换的总结
2021/01/25 Python
澳大利亚领先的男装零售连锁店:Lowes
2020/08/07 全球购物
BSTN意大利:德国街头和运动文化高品质商店
2020/12/22 全球购物
医科大学毕业生自荐信
2014/02/03 职场文书
公安学专业求职信
2014/07/27 职场文书
2015入党自传书范文
2015/06/26 职场文书
Python字典和列表性能之间的比较
2021/06/07 Python