python 描述器(译)

描述器定义

一般来说,描述器是一个”绑定行为“的对象属性(object attribute),它的访问控制被描述器协议方法重写,这些方法是 __get__(), __set__(),与 __delete__()

有这些方法的任一一个的对象叫做描述器。  描述器是类行为与函数行为的Python黑魔法。

描述器协议的方法为:

descr.__get__(self, obj, type=None) --> value
descr.__set__(self, obj, value)  --> none
descr.__delete__(self, obj) --> none

描述器的调用

描述器可以直接调用  : d.__get__(obj)

然而, 更常见的情况是描述器在属性访问时被自动调用,举例来说, obj.d 会在obj的__dict__中查找 d, 如果 d 定义了 __get__方法,那么 d.__get__(obj)会依据下面的优先规则被调用。

调用的细节取决于 obj 是一个还是一个实例,另外,描述器只对新式类或实例起作用,继承 object 的类叫做新式类。

对于对象(实例)来讲,方法 object.__getattribute__() 把 b.x 变为  type.__dict__[‘x’].__get__(b, type(b)) 。

具体顺序如下:

data  descriptor   >   __dict__    >    not data descriptor

对于类来讲,方法 type.__getattribute__()  把 b.x  变成  type(b).__dict__[‘x’].__get__(None, type(b)),用python来描述就是

def __getattribute__(self, key):
    "Emulate type_getattro() in Objects/typeobject.c"
    v = object.__getattribute__(self, key)
    if hasattr(v, '__get__'):
       return v.__get__(None, self)
    return v

重点总结如下:

1、描述符的调用时以为__getattribute__()

2、重写__getattribute_() 方法会阻止正常的描述器调用

3、object.__getattribute__() 和 type.__getattribute__()对__get__()的调用不一样

4、资料描述器总是比实例字典优先

5、非资料描述器可能被实例字典重用。



描述器的一个例子

class RevealAccess(object):
    """A data descriptor that sets and returns values
       normally and prints a message logging their access.
    """

    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        print 'Retrieving', self.name
        return self.val

    def __set__(self, obj, val):
        print 'Updating' , self.name
        self.val = val

>>> class MyClass(object):
    x = RevealAccess(10, 'var "x"')
    y = 5

>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5

这个协议非常简单,但提供了令人激动的可能。一些用途实在是太普通以致于它们被打包独立的函数。像属性 property(),方法 bound, unbound , 静态方法和类方法都是基于描述器协议的。 

英文原文:https://docs.python.org/2/howto/descriptor.html


Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
永久连接: http://www.nfvschool.cn/?p=642
标签:

发表评论