python 描述器,及property 的实现

来源:互联网 发布:礼物网络销售方案 编辑:程序博客网 时间:2024/06/05 10:17


 参考:https://pyzh.readthedocs.org/en/latest/Descriptor-HOW-TO-Guide.html


一个对象只要定义了  __get__(self,instance,owner),__set__(self,instance,value),__delete__(self,instance)__其中

的一个或多个,就是一个描述器。


如果一个对象同时定义了 __get__() 和 __set__(),它叫做资料描述器(data descriptor)。仅定义了 __get__() 的描述器叫非资料描述器(特别用于方法,当然其他用途也是可能的)

资料描述器和非资料描述器的区别在于:相对于实例的字典的优先级。如果实例字典中有与描述器同名的属性,如果描述器是资料描述器,优先使用资料描述器,如果是非资料描述器,优先使用字典中的属性。(译者注:这就是为何实例 a 的方法和属性重名时,比如都叫 foo Python会在访问 a.foo 的时候优先访问实例字典中的属性,因为实例函数的实现是个非资料描述器)




其中self 为描述起自身引用,instance是拥有此描述起的实例应用,owner是此描述的拥有者引用(无实例二字)。


class C(object):    def __init__(self,initval=None,name='Var'):        self.val=initval        self.name=name            def __get__(self,obj,objtype):        print(self,obj,objtype)        print('Retrieving',self.name)        return self.val    def __set__(self,obj,val):        print('Updating',self.name)        return self.nameclass MyClass(object):    x=C(10," var 'x'")    y=5m=MyClass()print(m.x)print(MyClass.x)

无实例时,instance为None

>>> <__main__.C object at 0x0000000003262A20> <__main__.MyClass object at 0x000000000330B048> <class '__main__.MyClass'>Retrieving  var 'x'10<__main__.C object at 0x0000000003262A20> None <class '__main__.MyClass'>Retrieving  var 'x'10>>>


Property()  的实现:

class Property(object):    "Emulate PyProperty_Type() in Objects/descrobject.c"    def __init__(self, fget=None, fset=None, fdel=None, doc=None):        self.fget = fget        self.fset = fset        self.fdel = fdel        self.__doc__ = doc    def __get__(self, obj, objtype=None):        if obj is None:            return self        if self.fget is None:            raise AttributeError, "unreadable attribute"        return self.fget(obj)    def __set__(self, obj, value):        if self.fset is None:            raise AttributeError, "can't set attribute"        self.fset(obj, value)    def __delete__(self, obj):        if self.fdel is None:            raise AttributeError, "can't delete attribute"        self.fdel(obj)