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局域网ip扫描示例分享
Apr 03 Python
python使用calendar输出指定年份全年日历的方法
Apr 04 Python
Python编程实现双链表,栈,队列及二叉树的方法示例
Nov 01 Python
Python语言实现百度语音识别API的使用实例
Dec 13 Python
python获取程序执行文件路径的方法(推荐)
Apr 26 Python
Python格式化输出%s和%d
May 07 Python
vue.js实现输入框输入值内容实时响应变化示例
Jul 07 Python
详解Python sys.argv使用方法
May 10 Python
Python button选取本地图片并显示的实例
Jun 13 Python
Pandas之MultiIndex对象的示例详解
Jun 25 Python
python3中替换python2中cmp函数的实现
Aug 20 Python
使用pygame实现垃圾分类小游戏功能(已获校级二等奖)
Jul 23 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文件打包 下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
2012/06/13 PHP
PHP实现视频文件上传完整实例
2014/08/28 PHP
使用PHP把HTML生成PDF文件的几个开源项目介绍
2014/11/17 PHP
PHP编程中的Session阻塞问题与解决方法分析
2017/08/07 PHP
PHP与SQL语句写一句话木马总结
2019/10/11 PHP
getElementById在任意一款浏览器中都可以用吗的疑问回复
2007/05/13 Javascript
javascript web对话框与弹出窗口
2009/02/22 Javascript
jquery UI 1.72 之datepicker
2009/12/29 Javascript
原生js实现跨浏览器获取鼠标按键的值
2013/04/08 Javascript
JS冒泡事件的快速解决方法
2013/12/16 Javascript
js实现文字在按钮上滚动的方法
2015/08/20 Javascript
JQUERY表单暂存功能插件分享
2016/02/23 Javascript
jQuery简单获取DIV和A标签元素位置的方法
2017/02/07 Javascript
angular.fromJson与toJson方法用法示例
2017/05/17 Javascript
JavaScript实现的可变动态数字键盘控件方式实例代码
2017/07/15 Javascript
浅谈vue项目优化之页面的按需加载(vue+webpack)
2017/12/11 Javascript
Node.js利用console输出日志文件的方法示例
2018/04/27 Javascript
浅谈Node 异步IO和事件循环
2019/05/05 Javascript
移动端吸顶fixbar的解决方案详解
2019/07/17 Javascript
[05:26]2014DOTA2西雅图国际邀请赛 iG战队巡礼
2014/07/07 DOTA
[02:28]DOTA2亚洲邀请赛附加赛 RECAP赛事回顾
2015/01/29 DOTA
Python中logging模块的用法实例
2014/09/29 Python
Django框架下在URLconf中指定视图缓存的方法
2015/07/23 Python
python:接口间数据传递与调用方法
2018/12/17 Python
Keras之自定义损失(loss)函数用法说明
2020/06/10 Python
Python实现一个优先级队列的方法
2020/07/31 Python
Python实现壁纸下载与轮换
2020/10/19 Python
Python通过字典映射函数实现switch
2020/11/06 Python
Python读取pdf表格写入excel的方法
2021/01/22 Python
python常量折叠基础知识点讲解
2021/02/28 Python
Pytorch实现WGAN用于动漫头像生成
2021/03/04 Python
StubHub意大利:购买和出售全球演唱会和体育赛事门票
2017/11/21 全球购物
BISSELL官网:北美吸尘器第一品牌
2019/03/14 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
《英英学古诗》教学反思
2014/04/11 职场文书
感恩教育观后感
2015/06/17 职场文书