Heim > Artikel > Backend-Entwicklung > Python-Dekoratoren
Es gibt viele Möglichkeiten, einen benutzerdefinierten Dekorator zu schreiben. Die einfachste und am leichtesten zu verstehende Möglichkeit besteht jedoch darin, eine Funktion zu schreiben, die eine Unterfunktion zurückgibt, die den ursprünglichen Funktionsaufruf kapselt.
Das allgemeine Muster ist wie folgt.
Python-Code
def my_decorator(function): def _my_decorator(*args, **kw): #在调用实际函数之前做些填充工作 res = function(*args, **kw) #做完某些填充工作之后 return res #返回子函数 return _my_decorator
Wenn der Dekorateur Parameter benötigt, muss er die zweite Verpackungsebene verwenden.
Python-Code
def my_decorator(arg1, arg2): def _my_decorator(function): def __my_decorator(*args, **kw): res = function() return res return __my_decorator return _my_decorator
bezieht sich auf
, da der Dekorator beim ersten Lesen des Moduls als Programm interpretiert wird geladen, daher muss ihre Verwendung auf die insgesamt anwendbaren Wrapper beschränkt werden. Wenn ein Dekorator an die Klassen- oder erweiterte Funktionssignatur einer Methode gebunden ist, sollte er in ein reguläres aufrufbares Objekt umgestaltet werden, um Komplexität zu vermeiden. Wenn Dekorateure mit APIs umgehen, ist es auf jeden Fall ein guter Ansatz, sie in einem leicht zu wartenden Modul zusammenzufassen.
Parameterprüfung:
Python-Code
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)
Caching:
Python-Code
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)
Agent:
Python-Code
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()
Kontextanbieter:
Python-Code
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()