Heim >Backend-Entwicklung >Python-Tutorial >Python-Dekorateure
Enthält:
1. Dekoratoren
2. Funktools
Werfen wir zunächst einen Blick auf die in Tornado verwendeten Dekoratoren
1. @tornado.web.authenticated
Zitat
Verzieren Sie Methoden damit, um zu erfordern, dass der Benutzer angemeldet ist.
Python-Code
def authenticated(method): """Decorate methods with this to require that the user be logged in.""" @functools.wraps(method) def wrapper(self, *args, **kwargs): if not self.current_user: if self.request.method in ("GET", "HEAD"): url = self.get_login_url() if "?" not in url: if urlparse.urlsplit(url).scheme: # if login url is absolute, make next absolute too next_url = self.request.full_url() else: next_url = self.request.uri url += "?" + urllib.urlencode(dict(next=next_url)) self.redirect(url) return raise HTTPError(403) return method(self, *args, **kwargs) return wrapper
Jede Methode, die die Benutzeranmeldung im nächsten Code überprüfen muss, kann diesen Dekorator verwenden, um viele wiederholte Bestätigungscodes zu vereinfachen @tornado.web.authenticated hinzufügen ist in Ordnung.
2. @tornado.web.asynchronous
Python-Code
def asynchronous(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): if self.application._wsgi: raise Exception("@asynchronous is not supported for WSGI apps") self._auto_finish = False with stack_context.ExceptionStackContext( self._stack_context_handle_exception): return method(self, *args, **kwargs) return wrapper
Dieser Dekorator setzt self._auto_finish auf False.
Als nächstes schreiben wir einen Dekorator für den Single-Interest-Modus:
Python-Code
def singleton(cls): instances = {} def get_instance(): if cls not in instances: instances[cls] = cls() return instances[cls] return get_instance @singleton class Foo: def __init__(self): pass class Bar: def __init__(self): pass f = Foo() m = Foo() print f,m,f == m a = Bar() b = Bar() print a,b,a == b
Ergebnis ist:
21d2d9bf249f94db1871fadbf2d577de 470eaeb2ff9dc104197c4e3d88f987ed True
b72eb228a034ad062191010b60df3ec2 e09655d088bb492c0aba7982f47c3e41 Dieser Dekorator implementiert Singleton der Klasse Pattern Das ist eine Klasse wird nur einmal instanziiert.
Verwenden Sie Dekoratoren, um Parameter und Methodenrückgabeergebnisse zu überprüfen:
#-*-coding:utf-8-*- def accepts(*types): def check_accepts(f): # assert len(types) == f.func_code.co_argcount def new_f(*args, **kwds): for (a, t) in zip(args, types): assert isinstance(a, t), \ "arg %r does not match %s" % (a,t) return f(*args, **kwds) new_f.func_name = f.func_name return new_f return check_accepts def returns(rtype): def check_returns(f): def new_f(*args, **kwds): result = f(*args, **kwds) assert isinstance(result, rtype), \ "return value %r does not match %s" % (result,rtype) return result new_f.func_name = f.func_name return new_f return check_returns @accepts(int, (int,float)) @returns((int,float)) def func(arg1, arg2): return arg1 * arg2 print func(1,2.0)
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,5000)
Ergebnis:
Assert a > 🎜>Zitat
Designziele:
* für beliebige Wrapper funktionieren, einschließlich benutzerdefinierter Callables und der vorhandenen integrierten Klassenmethode () und staticmethod(). Diese Anforderung bedeutet auch, dass eine Decorator-Syntax die Übergabe von Argumenten an den Wrapper-Konstruktor unterstützen muss
* mit mehreren Wrappern pro Definition arbeiten
* es sollte zumindest offensichtlich sein, was passiert Neue Benutzer können es getrost ignorieren, wenn sie ihren eigenen Code schreiben
* eine Syntax sein, „die ... nach der Erklärung leicht zu merken ist“
* zukünftige Erweiterungen nicht schwieriger machen
* einfach zu tippen sein ; Es wird erwartet, dass Programme, die es verwenden, es sehr häufig verwenden
* das schnelle Durchsuchen des Codes nicht erschweren. Es sollte dennoch einfach sein, nach allen Definitionen, einer bestimmten Definition oder den Argumenten zu suchen, die eine Funktion akzeptiert
* Sekundäre Support-Tools wie sprachsensitive Editoren und andere „Spielzeug-Parser-Tools da draußen“ nicht unnötig komplizieren.
* Ermöglichen Sie zukünftigen Compilern die Optimierung für Dekoratoren, mit der Hoffnung, dass ein JIT-Compiler für Python eingeführt wird Irgendwann in der Existenz erfordert dies tendenziell, dass die Syntax für Dekoratoren vor der Funktionsdefinition steht
* Bewegen Sie sich vom Ende der Funktion, wo sie derzeit verborgen ist, nach vorne, wo sie mehr ins Auge fällt [13 ]