您好,登錄后才能下訂單哦!
裝飾器的原理以及函數類型的裝飾器在網上有很多描述,本文我就只講我對于 將裝飾器定義為類的理解。
要將裝飾器定義為一個類,需要在類中聲明__call__
和__get__
方法,例子如下:
from time import time
class ttl_property(object):
def __init__(self, ttl=None):
self.ttl = ttl
def __call__(self, func):
def wrapper(*args,**kw):
if 'name' not in self.__dict__.keys():
self.__dict__['name']=(func(*args,**kw),time())
last=self.__dict__['name'][1]
value=self.__dict__['name'][0]
now=time()
if now-last>self.ttl:
value=func(*args,**kw)
self.__dict__['name']=(value,now)
return value
return wrapper
def __get__(self, instance, owner):
if instance is None:
return self
else:
return types.MethodType(self, instance)
def __set__(self, instance, value):
self.__dict__['name'] = (value, time())
from ttl_property import ttl_property
class Book(object):
"""
>>> b = Book()
>>> b.price
80.0
>>> b.price
80.0
>>> time.sleep(3)
>>> b.price
64.0
>>> b.price
64.0
>>> time.sleep(3)
>>> b.price
51.2
"""
def __init__(self):
self._price = 100.0
@ttl_property(ttl=2)
def price(self):
self._price = self._price * 0.8
return self._price
這是我在一個網站上做的實驗,在這個實驗中需要定義一個裝飾器類ttl_property來裝飾Book類中的函數,__call__
函數可以將類的調用和函數類似,具體請查詢網上資料。
我要著重強調兩點:
1:裝飾器類中的__get__
方法很重要,因為在裝飾器中返回的函數并不是原本類中的函數,也就是說在原本類所對應的實例中,這個函數并不存在,所以如果沒有__get__
方法,那么調用就會出問題;那么types.MethodType(self, instance)就是將方法和實例綁定起來,這樣在這個實例中就包含了這個方法,就可以順利調用了。
2:如果在原來的方法中需要使用self,那么在裝飾器返回的方法中也要包含self參數,不然就不行
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。