32.3-描述器Descriptors概念

2020-01-01  本文已影响0人  BeautifulSoulpy

人生苦短,所以每天不要带着遗憾醒来!

总结:

  1. 数据描述器比我们实例字典优先;
  2. 知道不同条件下谁优先的就行;与反射的方法不可混用;

描述器

Python中,一个类实现了 _get_ 、 _set_ 、 _delete_ 三个方法中的任何一个方法,就是描述器。
如果仅实现了 _get_ ,就是非数据描述符 non-data descriptor
同时实现了 _get_ 、 _set_ 就是数据描述符 data descriptor
如果一个类的类属性设置为描述器实例,那么它被称为owner属主。

用到3个魔术方法: _get_() 、 _set_() 、 _delete_()
方法签名如下
object._get(self, instance, owner)
object._set
(self, instance, value)
object._delete_(self, instance)
self指代当前实例,调用者
instance 是owner的实例
owner 是属性的所属的类

class A:
    def __init__(self):
        print('A().init~~~~~~~~~~')
        self.a1 = 100
    
    def __get__(self,instance,owner):
        print(self)   #A实例本身
        print(instance)  # None,如果使用B的实例来访问,B的实例;
        print(owner)  #B
        print("~~~~~~~~~~~~~~~~~~~")
        return self
        
    def __set__(self,instance,value):
        print(self)
        print(instance)
        print(value)
        print('--------------------')
        
    def __delete__(self,instance):
        print(instance)
        
class B:
    x = A()
    def __init__(self):
        print('B().init~~~~~~~~~~~~~')
print(B.x)
#----------------------------------------------------
A().init~~~~~~~~~~
<__main__.A object at 0x000002089F30DCC0>
None
<class '__main__.B'>
~~~~~~~~~~~~~~~~~~~
None

描述器由两个类构成:而类B的x属性是类A的实例,所以类A先初始化,所以打印A.init。
然后执行到打印B.x.a1。

因为定义了 _get_ 方法,类A就是一个描述器,对类B或者类B的实例的x属性读取,成为对类A的实例的访问,就会调用 _get_ 方法

访问: _get(self, instance, cls) # instance 代表实例本身,cls 表示类本身,使用类直接访问时,instance 为 None
赋值: _set
(self, instance, value) # instance 为实例,value 为值
删除: _delete_(self, instance) # instance 为实例

上一篇下一篇

猜你喜欢

热点阅读