描述符(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
{}

从上述两个例子中可以看到,类Bvalue属性是一个描述符,当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将类固定为方法的第一个参数。

总结

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

最新文章

  1. 在Ubuntu14.04_ROS_indigo上安装Kinect2驱动和bridge
  2. Kotlin语法(函数和lambda表达式)
  3. mysql 控制台上传数据库
  4. PHP判断当前访问的是 微信、iphone、android 浏览器
  5. $( ).focus()与$( )[0].focus()区别
  6. MSSQL Server 导入/导出到远程服务器
  7. leecode 归并排序 链表(java)
  8. MediaPlayer+SurfaceView 视频播放 示例
  9. 14.5.1 Resizing the InnoDB System Tablespace
  10. 201521145048《Java程序设计》第5周学习总结
  11. Android高版本联网失败报错:Cleartext HTTP traffic to xxx not permitted解决方法
  12. Azure CosmosDB (11) MongoDB概念
  13. rds下载备份集
  14. 移动rem自适应
  15. FortiGate路由模式--静态地址线路上网配置
  16. PCB板的三种敷铜方法解析
  17. 20135234mqy-——信息安全系统设计基础第十三周学习总结
  18. ueditor的上传文件漏洞(c#)
  19. Python面向对象:类、实例与访问限制
  20. centos7-windows10 双系统安装

热门文章

  1. TensorFlow 官方文档中文版
  2. WinMain和MFC的差别
  3. ES6 一些常用使用
  4. 5313 [JL]判断邮箱地址 升级版
  5. shell 切割文件
  6. Baum–Welch algorithm
  7. Recommendation system
  8. oc79--数组的内存管理
  9. 【HTML5】基于HTML5的高性能动画与游戏
  10. BZOJ 2829 凸包