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中关于日期时间处理的问答集锦
Mar 08 Python
python正则匹配抓取豆瓣电影链接和评论代码分享
Dec 27 Python
python实现中文输出的两种方法
May 09 Python
Python面向对象思想与应用入门教程【类与对象】
Apr 12 Python
图文详解python安装Scrapy框架步骤
May 20 Python
Pandas之Dropna滤除缺失数据的实现方法
Jun 25 Python
python读取.mat文件的数据及实例代码
Jul 12 Python
python读取指定字节长度的文本方法
Aug 27 Python
Python通过Tesseract库实现文字识别
Mar 05 Python
详解pandas绘制矩阵散点图(scatter_matrix)的方法
Apr 23 Python
Python+Selenium实现自动化的环境搭建的步骤(图文)
Sep 01 Python
Python语言编写智力问答小游戏功能
Oct 13 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实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
需要做特殊处理的DOM元素属性的访问
2010/11/05 Javascript
javascript表单验证使用示例(javascript验证邮箱)
2014/01/07 Javascript
IE下Ajax缓存问题的快速解决方法(get方式)
2014/01/09 Javascript
JavaScript使用yield模拟多线程的方法
2015/03/19 Javascript
jQuery使用attr()方法同时设置多个属性值用法实例
2015/03/26 Javascript
浅谈javascript实现八大排序
2015/04/27 Javascript
jQuery插件formValidator实现表单验证
2016/05/23 Javascript
javascript常用经典算法详解
2017/01/11 Javascript
微信小程序 简单教程实例详解
2017/01/13 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
vant实现购物车功能
2020/06/29 Javascript
Vue(定时器)解决mounted不能获取到data中的数据问题
2020/07/30 Javascript
[03:03]DOTA2校园争霸赛 济南城市决赛欢乐发奖活动
2013/10/21 DOTA
Python实现的二维码生成小软件
2014/07/11 Python
Python中的map()函数和reduce()函数的用法
2015/04/27 Python
python基础知识小结之集合
2015/11/25 Python
Python 绘图库 Matplotlib 入门教程
2018/04/19 Python
python 对dataframe下面的值进行大规模赋值方法
2018/06/09 Python
python 字典中文key处理,读取,比较方法
2018/07/06 Python
基于python代码实现简易滤除数字的方法
2018/07/17 Python
Python实现定制自动化业务流量报表周报功能【XlsxWriter模块】
2019/03/11 Python
使用CSS3制作饼状旋转载入效果的实例
2015/06/23 HTML / CSS
canvas实现扭蛋机动画效果的示例代码
2018/10/17 HTML / CSS
美国运动鞋和运动服零售商:Footaction
2017/04/07 全球购物
电气自动化专业职业规划范文
2014/02/16 职场文书
小学优秀班干部事迹材料
2014/05/25 职场文书
文案策划专业自荐信
2014/07/07 职场文书
员工教育培训协议书
2014/09/27 职场文书
北京大学中文系教授推荐的10本小说
2019/08/08 职场文书
熟背这些句子,让您的英语口语突飞猛进(135句)
2019/09/06 职场文书
Python max函数中key的用法及原理解析
2021/06/26 Python
Java中PriorityQueue实现最小堆和最大堆的用法
2021/06/27 Java/Android
解决使用了nginx获取IP地址都是127.0.0.1 的问题
2021/09/25 Servers
python DataFrame中stack()方法、unstack()方法和pivot()方法浅析
2022/04/06 Python
windows server2012 R2下安装PaddleOCR服务的的详细步骤
2022/09/23 Servers