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中为什么要用self探讨
Apr 14 Python
python实现将英文单词表示的数字转换成阿拉伯数字的方法
Jul 02 Python
Python编程实现生成特定范围内不重复多个随机数的2种方法
Apr 14 Python
Python matplotlib画图实例之绘制拥有彩条的图表
Dec 28 Python
VScode编写第一个Python程序HelloWorld步骤
Apr 06 Python
pytorch + visdom 处理简单分类问题的示例
Jun 04 Python
python使用turtle绘制分形树
Jun 22 Python
对Python 数组的切片操作详解
Jul 02 Python
Python多线程原理与用法详解
Aug 20 Python
在 Pycharm 安装使用black的方法详解
Apr 02 Python
Python selenium环境搭建实现过程解析
Sep 08 Python
详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用
Jan 21 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递归返回值时出现的问题解决办法
2013/02/19 PHP
CI框架数据库查询之join用法分析
2016/05/18 PHP
Thinkphp 中 distinct 的用法解析
2016/12/14 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
PHP单元测试配置与使用方法详解
2019/12/27 PHP
Javascript的匿名函数小结
2009/12/31 Javascript
js冒泡、捕获事件及阻止冒泡方法详细总结
2014/05/08 Javascript
JQuery通过AJAX从后台获取信息显示在表格上并支持行选中
2015/09/15 Javascript
javascript实现tab切换特效
2015/11/12 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
2015/11/25 Javascript
jQuery animate easing使用方法图文详解
2016/06/17 Javascript
浅谈js在html中的加载执行顺序,多个jquery ready执行顺序
2016/11/26 Javascript
PHP+jquery+ajax实现分页
2016/12/09 Javascript
详解微信小程序 wx.uploadFile 的编码坑
2017/01/23 Javascript
JQuery实现文字无缝滚动效果示例代码(Marquee插件)
2017/03/07 Javascript
angularJs利用$scope处理升降序的方法
2018/10/08 Javascript
Vue自定义属性实例分析
2019/02/23 Javascript
Vue2.0实现组件之间数据交互和通信操作示例
2019/05/16 Javascript
微信小程序通过一个json实现分享朋友圈图片
2019/09/03 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
解决LayUI数据表格复选框不居中显示的问题
2019/09/25 Javascript
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
[01:03:37]Secret vs VGJ.S Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
给Python中的MySQLdb模块添加超时功能的教程
2015/05/05 Python
python框架中flask知识点总结
2018/08/17 Python
Python定义函数功能与用法实例详解
2019/04/08 Python
tensorflow的ckpt及pb模型持久化方式及转化详解
2020/02/12 Python
css3 按钮 利用css3实现超酷下载按钮
2013/03/18 HTML / CSS
澳大利亚在线生活方式商店:Mytopia
2018/07/08 全球购物
员工培训邀请函
2014/01/11 职场文书
会计学专业学生的求职信范文
2014/01/27 职场文书
爱岗敬业演讲稿
2014/05/05 职场文书
中学学校门卫岗位职责
2014/08/15 职场文书
初婚未育证明样本
2015/06/18 职场文书
mysql批量新增和存储的方法实例
2021/04/07 MySQL
win11自动弹出虚拟键盘怎么关闭? Win11关闭虚拟键盘的技巧
2023/01/09 数码科技