编写自定义装饰器有许多方法,但最简单和最容易理解的方法是编写一个函数,返回封装原始函数调用的一个子函数。
通用的模式如下。
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)
代理:
Python代码
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()
上下文提供者:
Python代码
from threading import RLock lock = RLock() def synchronized(function): def _synchronized(*args, **kw): lock.acquire() try: return function(*args, **kw) finally: lock.release() return _synchronized @synchronized def thread_safe(): print 'haha' thread_safe()