class cached_property(object): def __init__(self, func, name=None, doc=None): self.__name__ = name or func.__name__ self.__module__ = func.__module__ self.__doc__ = doc or func.__doc__ self.func = func def __get__(self, obj, type=None): if obj is None: return self value = obj.__dict__.get(self.__name__, None) if value is None: value = self.func(obj) obj.__dict__[self.__name__] = value return value
今天在werkzurg上看到上面的代碼,寫得真是精彩!html
一般咱們descrator是這麼寫的python
def cached_property(func): def _(*args, **kwargs): return func(*args, **kwargs) return _
從代碼形式上看,這是一個函數調用,返回一個函數,在python語法上decorator爲下面的編寫方式:緩存
@cached_property def func(): return 42
而代碼的執行方式和cached_property(func)是同樣的,這是一種閉包的形式,這種形式和定義一個object,__init__第一個參數是func,以後定義一個__call__是等價的。在werkzurg中採用了前面的方式__init__來獲取和decorator相同的行爲,而__init__返回的是cached_property對象,這個對象使用__get__這個descriptor特性。閉包
當調用@cached_property修飾的屬性名稱時,便會調用生成的對象的__get__方法,從而能夠更加仔細的調用func方法獲取具體的值,從而緩存起來!!!函數
對descriptor不熟悉的能夠看python文檔:http://docs.python.org/2/howto/descriptor.htmlspa
perfect!code