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中关于使用模块的基础知识
May 24 Python
用Python解决计数原理问题的方法
Aug 04 Python
Python3 queue队列模块详细介绍
Jan 05 Python
python使用TensorFlow进行图像处理的方法
Feb 28 Python
Python将图片转换为字符画的方法
Jun 16 Python
Python闭包函数定义与用法分析
Jul 20 Python
python中时间、日期、时间戳的转换的实现方法
Jul 06 Python
python3 实现调用串口功能
Dec 26 Python
Win10里python3创建虚拟环境的步骤
Jan 31 Python
python实现一次性封装多条sql语句(begin end)
Jun 06 Python
深入了解NumPy 高级索引
Jul 24 Python
Python爬虫爬取有道实现翻译功能
Nov 27 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
dedecms模板标签代码官方参考
2007/03/17 PHP
PHP学习笔记之字符串编码的转换和判断
2014/05/22 PHP
使用WAMP搭建PHP本地开发环境
2017/05/10 PHP
visual studio code 调试php方法(图文详解)
2017/09/15 PHP
javascript判断单选框或复选框是否选中方法集锦
2007/04/04 Javascript
关于IE、Firefox、Opera页面呈现异同 写脚本很痛苦
2009/08/28 Javascript
JavaScript实现自己的DOM选择器原理及代码
2013/03/04 Javascript
js对文章内容进行分页示例代码
2014/03/05 Javascript
超链接的禁用属性Disabled使用示例
2014/07/31 Javascript
javascript表单控件实例讲解
2016/09/13 Javascript
浅析Node.js:DNS模块的使用
2016/11/23 Javascript
jQuery动态追加页面数据以及事件委托详解
2017/05/06 jQuery
20行JS代码实现网页刮刮乐效果
2017/06/23 Javascript
BootStrap导航栏问题记录
2017/07/31 Javascript
JavaScript实现的原生态Tab标签页功能【兼容IE6】
2017/09/18 Javascript
在 Vue.js中优雅地使用全局事件的方法
2019/02/01 Javascript
[01:08:24]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第一场 2月5日
2021/03/11 DOTA
如何准确判断请求是搜索引擎爬虫(蜘蛛)发出的请求
2015/10/13 Python
利用python循环创建多个文件的方法
2018/10/25 Python
python Django的web开发实例(入门)
2019/07/31 Python
Python 调用 ES、Solr、Phoenix的示例代码
2020/11/23 Python
基于HTML5 audio元素播放声音jQuery小插件
2011/05/11 HTML / CSS
瑞典Happy Socks美国官网:购买色彩斑斓的快乐袜子
2016/10/19 全球购物
定制别致的瑜伽垫:Sugarmat
2019/06/21 全球购物
波兰最早的运动鞋精品店之一:Street Supply
2019/08/29 全球购物
英国网上自行车商店:Tredz Bikes
2019/10/29 全球购物
后勤服务中心总经理工作职责
2014/03/03 职场文书
4s店市场专员岗位职责
2014/04/09 职场文书
道德之星事迹材料
2014/05/03 职场文书
体育节口号
2014/06/19 职场文书
公司自我介绍演讲稿
2014/08/21 职场文书
励志演讲稿800字
2014/08/21 职场文书
2014乡镇干部对照检查材料思想汇报
2014/09/26 职场文书
电工实训报告总结
2014/11/05 职场文书
七年级作文之《我和我的祖国》观后感作文
2019/10/18 职场文书
Golang 语言控制并发 Goroutine的方法
2021/06/30 Golang