맞춤 데코레이터를 작성하는 방법에는 여러 가지가 있지만 가장 간단하고 이해하기 쉬운 방법은 원래 함수 호출을 캡슐화하는 하위 함수를 반환하는 함수를 작성하는 것입니다.
일반적인 패턴은 다음과 같습니다.
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를 처리할 때 좋은 접근 방식은 쉽게 유지 관리할 수 있는 모듈에 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()
컨텍스트 제공자:
파이썬 코드
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()