編寫自訂裝飾器有許多方法,但最簡單且最容易理解的方法是編寫一個函數,並傳回封裝原始函數呼叫的一個子函數。
通用的模式如下。
Python程式碼
def my_decorator(function): def _my_decorator(*args, **kw): #在调用实际函数之前做些填充工作 res = function(*args, **kw) #做完某些填充工作之后 return res #返回子函数 return _my_decorator
當裝飾器需要參數時,必須使用第二級封裝。
Python代碼
def my_decorator(arg1, arg2): def _my_decorator(function): def __my_decorator(*args, **kw): res = function() return res return __my_decorator return _my_decorator
引用
因為裝飾器在模組第一次被讀取時由解釋程序裝入,所以它們的使用必須受限於總體上可以應用的封裝器。如果裝飾器與方法的類別或所增強的函數簽章綁定,它應該被重構為常規的可呼叫對象,從而避免複雜性。在任何情況下,當裝飾器處理API時,一個好的方法是將它們聚集在一個易於維護的模組中。
參數檢查:
Python代碼
def check_param_isvalid(): def check(method): def check_param(*args,**kwargs): for a in args: assert isinstance(a, int),"arg %r does not match %s" % (a,int) assert a > 100000,"arg %r must gt 100000" % a return method(*args, **kwargs) return check_param return check @check_param_isvalid() def foo(*args): print args foo(200000,500000)
快取:
Python
import time import hashlib import pickle cache = {} def is_obsolete(entry, duration): return time.time() - entry['time'] > duration def computer_key(function, args, kw): key = pickle.dumps((function.func_name, args, kw)) return hashlib.sha1(key).hexdigest() def memoize(duration=30): def _memoize(function): def __memoize(*args, **kw): key = computer_key(function, args, kw) if key in cache and not is_obsolete(cache[key], duration): print 'wo got a winner' return cache[key]['value'] result = function(*args, **kw) cache[key] = {'value':result,'time':time.time()} return result return __memoize return _memoize @memoize() def very_complex_stuff(a,b): return a + b print very_complex_stuff(2,2)
上下文提供者:
class User(object): def __init__(self, roles): self.roles = roles class Unauthorized(Exception): pass def protect(role): def _protect(function): def __protect(*args, **kw): user = globals().get('user') if user is None or role not in user.roles: raise Unauthorized("I won't tell you") return function(*args, **kw) return __protect return _protect tarek = User(('admin', 'user')) bill = User(('user',)) class MySecrets(object): @protect('admin') def waffle_recipe(self): print 'use tons of butter!' these_are = MySecrets() user = tarek these_are.waffle_recipe() user = bill these_are.waffle_recipe()