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

相關文章
相關標籤/搜索