人生苦短,所以每天不要带着遗憾醒来!
总结:
- 数据描述器比我们实例字典优先;
- 知道不同条件下谁优先的就行;与反射的方法不可混用;
描述器
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 为实例
网友评论