深入理解Python描述符
来源:互联网 发布:北宋 纪录片 知乎 编辑:程序博客网 时间:2024/05/22 06:59
最近在看《流畅的Python》关于描述符的章节,平时也不经意间会接触到cached_property、sqlalchemy的Column、甚至内置的property都是描述符。在网上也看到过关于描述符的讲解,但是并没有区分覆盖型描述符和非覆盖型描述符,因为这两者获取属性的优先级链不一样,下面来具体说说。
为什么要区分覆盖型和非覆盖型?
《流畅的Python》中写到,“Python存取属性的方式特别不对等,通过实例读取属性时,通常返回的是实例中定义的属性;但是,如果实例中没有指定的属性,那么会获取类属性。而为实例中的属性赋值时,通常会在实例中创建属性,根本不影响类。这种 不对等的处理方式对描述符也有影响。”
根据描述符中是否定义了__set__方法可以把描述符分为覆盖型和非覆盖型,有__set__方法就是覆盖型描述符,覆盖型描述符还可以分为两类,有__get__方法的覆盖型和没有__get__方法的覆盖型。
1. 非覆盖型的获取属性的优先级链是,__getattribute__->找__dict__->找描述符,这条链的规则给了"缓存属性"理论支持,如下
class cached_property(object): def __init__(self, func): self.__doc__ = getattr(func, '__doc__') self.func = func def __get__(self, obj, cls): if obj is None: return self value = obj.__dict__[self.func.__name__] = self.func(obj) return value当pbj.__dict__里有了self.func.__name__时,下次就不会再调用这个描述符了
2. 有__get__方法的覆盖型的获取属性的优先级链是,__getattribute__->找描述符,同时__set__方法也会覆盖对实例属性的赋值操作,就是说任何外部对属性的赋值都将被__set__捕获,同时获取属性也是通过__get__方法获取,__dict__不再起直接作用。
3. 没有__get__方法的覆盖型的获取属性优先级链是
在没有对属性赋值时是__getattribute__->找描述符(返回描述符对象本身),对属性赋值了之后是__getattribute__->找__dict__->找描述符,举个例子
class OverridingNoGet: """an overriding descriptor without ``__get__``""" def __set__(self, instance, value): print_args('set', self, instance, value)class Managed: over_no_get = OverridingNoGet() def spam(self): print('-> Managed.spam({})'.format(display(self)))>>> obj.over_no_get # doctest: +ELLIPSIS<descriptorkinds.OverridingNoGet object at 0x...>>>> Managed.over_no_get # doctest: +ELLIPSIS<descriptorkinds.OverridingNoGet object at 0x...>>>> obj.over_no_get = 7-> OverridingNoGet.__set__(<OverridingNoGet object>, <Managed object>, 7)>>> obj.over_no_get # doctest: +ELLIPSIS<descriptorkinds.OverridingNoGet object at 0x...>>>> obj.__dict__['over_no_get'] = 9>>> obj.over_no_get9>>> obj.over_no_get = 7-> OverridingNoGet.__set__(<OverridingNoGet object>, <Managed object>, 7)>>> obj.over_no_get9
再来谈谈描述符的线程安全问题
多个线程,每个线程都会进入一次描述符,所以控制线程安全还得根据描述符__get__方法内是否存在临界区,但是__set__方法一般都要锁来保证线程安全了
- 深入理解Python描述符
- Linux内核笔记--深入理解文件描述符
- 《深入理解Linux内核》-3.2. 进程描述符
- Python 深入理解yield
- Python 深入理解yield
- Python 深入理解yield
- Python 深入理解yield
- Python 深入理解yield
- 深入理解 Python import
- 深入理解 Python
- python---深入理解yield
- 深入理解python super
- 深入理解计算机系统-之-内存寻址(三)--分段管理机制(段描述符,段选择子,描述符表)
- 《深入理解Linux内核3rd》学习笔记——进程描述符
- 深入理解python之self
- 深入理解python之self
- 《深入理解Python》读书笔记Ⅰ
- 《深入理解Python》读书笔记Ⅱ
- Ubuntu 16.04出现:Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/
- 对字符串数组进行ASCII码规则排序
- js小结
- idea 关于自动导包的设置
- python csv写入多列
- 深入理解Python描述符
- 前端性能优化
- 林学——知识点1
- Android中版本更新(使用HttpURLConnection网络请求)
- Android使用Mina建立长连接
- 剑指offer-23:二叉树的层次遍历
- 浏览器内部工作原理
- 【Bitmap算法浅谈篇】Mysql应用Bitmap
- c#总结4