python 描述器
语法简析一般来说,描述器(descriptor)是一个有”绑定行为”的对象属性(object attribute),它的属性访问被描述器协议方法重写。这些方法是 descr.__get__(self,obj,type=None) --> value descr.__set__(self,value) --> None descr.__delete__(self,obj) --> None 描述器本质上是一个类对象,该对象定义了描述器协议三种方法中至少一种。而这三种方法只有当类的实例出现在一个所有者类(owner class)之内时才有效,也就是说,描述器必须出现在所有者类或其父类的字典 描述器往往以装饰器的方式被使用,导致二者常被混淆。描述器类和不带参数的装饰器类一样,都传入函数对象作为参数,并返回一个类实例,所不同的是,装饰器类返回 callable 的实例,描述器则返回描述器实例。 记住上面的话,下面我们举例说明。 @PropertyPython 内置的
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 if doc is None and fget is not None: doc = fget.__doc__ self.__doc__ = doc def __get__(self,objtype=None): if obj is None: return self if self.fget is None: raise AttributeError("unreadable attribute") return self.fget(obj) def __set__(self,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) def getter(self,fget): return type(self)(fget,self.fset,self.fdel,self.__doc__) def setter(self,fset): return type(self)(self.fget,fset,self.__doc__) def deleter(self,fdel): return type(self)(self.fget,fdel,self.__doc__)
class C(object): def __init__(self): self._x = None @Property def x(self): """I‘m the ‘x‘ property.""" return self._x @x.setter def x(self,value): assert value > 0 self._x = value @x.deleter def x(self): del self._x 我们结合源代码和用法来分析
x = Property(x) 函数
y = x.setter(y) 新描述器就被
In [123]: c = C() In [124]: c.x = 1 In [125]: c.x Out[125]: 1 In [126]: c.x = 0 --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-126-b03deb420dcb> in <module>() ----> 1 c.x = 0 <ipython-input-50-95b8686aa4bd> in __set__(self,value) 20 if self.fset is None: 21 raise AttributeError("can‘t set attribute") ---> 22 self.fset(obj,value) 23 24 def __delete__(self,obj): <ipython-input-116-379a4e5fa639> in x(self,value) 10 @x.setter 11 def x(self,value): ---> 12 assert value > 0 13 self._x = value 14 AssertionError: 与一般的属性访问不同, 那么,描述器是怎样被访问到的呢? 调用描述器有两类描述器:如果同时定义了 如前文所说,描述器常在所有者类或其实例中被调用。 对于实例对象, 对于类, 有几点需要牢记的:
非资料描述器与类方法Python 面向对象的特征建立在基于函数的环境之上。Python 用非资料描述器将二者无缝结合。 方法和普通函数唯一的区别就是,一般方法的第一个参数引用了当前实例,即通常命名为 Python 中的函数,可以被认为是一个实现了 class Function(object): . . . def __get__(self,objtype=None): "Simulate func_descr_get() in Objects/funcobject.c" return types.MethodType(self,objtype) 当函数作为属性被访问时,非资料描述器把函数变为一个方法,把实例调用 更多绑定和转换参见下表。
静态方法是特殊的方法,可以无须实例化而在类中被直接调用,这时当然无法提供合法的 class StaticMethod(object): "Emulate PyStaticMethod_Type() in Objects/funcobject.c" def __init__(self,f): self.f = f def __get__(self,objtype=None): return self.f 类方法是另一种特殊的方法,无需当前实例 class ClassMethod(object): "Emulate PyClassMethod_Type() in Objects/funcobject.c" def __init__(self,klass=None): if klass is None: klass = type(obj) def newfunc(*args): return self.f(klass,*args) return newfunc (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |