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
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__)
認真看看就明白了
-----------------------------------
很好的學習參考:
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