ホームページ >バックエンド開発 >Python チュートリアル >Python デコレータ
カスタム デコレータを記述する方法はたくさんありますが、最もシンプルで理解しやすいのは、元の関数呼び出しをカプセル化するサブ関数を返す関数を記述することです。
一般的なパターンは次のとおりです。
Python コード
def my_decorator(function): def _my_decorator(*args, **kw): #在调用实际函数之前做些填充工作 res = function(*args, **kw) #做完某些填充工作之后 return res #返回子函数 return _my_decorator
デコレータがパラメータを必要とする場合、第 2 レベルのカプセル化を使用する必要があります。
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
Quote
デコレーターはモジュールが最初に読み取られるときにインタープリターによってロードされるため、その使用は全体に適用できるラッパーに限定する必要があります。デコレータがメソッドのクラスまたは拡張関数シグネチャにバインドされている場合は、複雑さを避けるために、デコレータを通常の呼び出し可能オブジェクトにリファクタリングする必要があります。いずれの場合でも、デコレーターが 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()