轻松理解Python 中的 descriptor
定义
通常,一个descriptor是具有“绑定行为”的对象属性。所绑定行为可通过descriptor协议被自定义的__get__(),__set__()和__delete__()方法重写。如果一个对象的上述三个方法任意一个被重写,则就可被称为descriptor。
属性的默认操作是从对象字典中获取、设置和删除一个属性。例如,a.x有一个查找链,先a.__dict__['x'],若没有则type(a).__dict__['x'],若没有增往上查找父类直到元类。如果查找链中,对象被定义了descriptor方法,Python就会覆盖默认行为。
Descriptor是一个强大的工具,虽然开发者不常接触到它,但它其实就是类、属性、函数、方法、静态方法、类方法以及super()背后的运行机制。
Descriptor协议
三个方法原型如下所示:
descr.__get__(self,obj,type=None)-->value descr.__set__(self,obj,value)-->None descr.__delete__(self,obj)-->None
数据descriptor是同时具有__get__()和__set__()方法的对象,若只有__get__()方法,则为非数据descriptor。如果实例字典中有和数据descriptor同名的入口,则数据descriptor优先级更高。相反,非数据descriptor优先级低。
让__set__()方法抛出异常,就能创建一个只读数据descriptor。
调用descriptor
descriptor可以直接通过方法名调用。例如,d.__get__(obj)。
而通过访问对象属性,自动调用descriptor才是更通用的做法。例如,如果d定义了方法__get__(),则obj.d会调用d.__get__(obj)。
对于对象,b.x会被转换成type(b).__dict__['x'].__get__(b,type(b))。而对于类(是的,类也可以调用),B.x会被转换成B.__dict__['x'].__get__(None,B)。
Descriptor例子
classRevealAccess(object):
"""Adatadescriptorthatsetsandreturnsvalues
normallyandprintsamessageloggingtheiraccess.
"""
def__init__(self,initval=None,name='var'):
self.val=initval
self.name=name
def__get__(self,obj,objtype):
print('Retrieving',self.name)
returnself.val
def__set__(self,obj,val):
print('Updating',self.name)
self.val=val
>>>classMyClass(object):
...x=RevealAccess(10,'var"x"')
...y=5
...
>>>m=MyClass()
>>>m.x
Retrievingvar"x"
10
>>>m.x=20
Updatingvar"x"
>>>m.x
Retrievingvar"x"
20
>>>m.y
5
总结
以上所述是小编给大家介绍的Python中的descriptor,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!