Python descriptor 以及 内置property()函数

Python Descriptor html

 

1, Python Descriptor是这样一个对象python

 

它按照descriptor协议, 有这样的属性之一函数

def __get__(self, obj, type=None)  #  会返回一个value
def __set__(self, obj, value)   # 返回None
def __delete__(self, obj)  # 返回None

这样的对象就是一个descriptor学习

 

 

2, descriptor的特性spa

倘若有一个对象t, 咱们去引用它的一个属性acode

t.a

可是发现a是一个descriptorhtm

那么不会返回a, 而是会去调用a相应的__get__, __set__, __delete__对象

 

那么什么状况调用那个呢?以下blog

 

  • v = t.a   <---->   v = __get__(a, t)
  • t.a = v   <----->  __set__(a, t, v)
  • del t.a   <----->  __delete__(a, t)

 

 

3, descriptor是如何实现的ip

只有new-style objects或class的属性在被引用时,descriptor的特性才能起做用

从 object 派生的类就是 new-style class

class T(object):
    pass

 

那么这大概是怎么回事呢?

 

是由于object有__getattribute__属性, 这个属性的实现确保了descriptor机制

因此若是咱们重写了__getattribute__, 那么就能够消除descriptor机制

 

__getattribute__是如何实现的,之后探讨, 参考2中有一点点例子

 

 

内置函数 property()

Python有内置property()函数, 它能够直接作函数,也能够用来作装饰器, 它的使用方式以下, 例子来自参考3

class Test(object):
    def getx(self):
           return self._x
    def setx(self, v):
           self._x = v
    def deletex(self):
           del self._x

    x = property(getx, setx, deletex, ''' __doc__''')

而上面的代码等价于下面的

class Test(object):
    @property
    def x(self):
        return self._x
    
    @x.setter
    def x(self, v):
        self._x = v

    @x.deleter
    def x(self):
        del self._x

 

对于Test的x属性,能够这么用

t = Test()
t.x = 5
print t.x
del t.x

 

那么为何property()能够这么用,尤为是第二种中, x.setter和 x.deleter还能够作装饰器呢?

 

首先咱们要先明白装饰器是什么

 

property()会返回一个Property对象, 而后咱们来看一个用Python模拟的Property类的实现,  摘自参考1

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, 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)

    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.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)

 

认真看看就明白了

  • Property对象是Descriptor
  • Property.setter 和 Property.deleter 都是装饰器,他们和property同样,都是返回Property()对象,不一样的是 @property设置 fget ,  setter和 deleter分别设置 fset, 和 fdel

 

 -----------------------------------

很好的学习参考:

1, http://stackoverflow.com/questions/17330160/python-how-does-decorator-property-work

2, http://docs.python.org/3.2/howto/descriptor.html

3, http://docs.python.org/3.2/library/functions.html#property

相关文章
相关标签/搜索