포함 내용:
1. 데코레이터
2. functools
먼저 토네이도에 사용되는 데코레이터를 살펴보겠습니다
1. @tornado.web.authenticated
인용문
이로 메소드를 장식하여 사용자가 로그인하도록 요구합니다.
Python 코드
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
다음 코드에서 사용자 로그인을 확인해야 하는 모든 메소드는 이 데코레이터를 사용하면 반복되는 많은 인증 코드를 단순화할 수 있습니다. @tornado.web.authenticated를 추가해도 괜찮습니다.
2. @tornado.web.asynchronous
Python 코드
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
이 데코레이터는 self._auto_finish를 False로 설정합니다.
다음으로 단일 관심 모드 데코레이터를 작성해 보겠습니다.
Python 코드
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
결과는 다음과 같습니다.
<__main__.Foo 인스턴스 0x103152c20> <0x103152c20의 __main__.Foo 인스턴스> True
<0x103152c68의 __main__.Bar 인스턴스> False
@singleton 이 데코레이터는 패턴 클래스를 구현합니다. 수업을 보장합니다 한 번만 인스턴스화됩니다.
데코레이터를 사용하여 매개변수 및 메소드 반환 결과 확인:
Python 코드
#-*-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)
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,5000)
결과:
assert a > 100000,"arg %r must gt 100000" % a
AssertionError: arg 5000 must gt 100000
인용문
디자인 목표:
새 구문은
* 사용자 정의 콜러블 및 기존 내장 클래스 메서드() 및 staticmethod(). 이 요구 사항은 데코레이터 구문이 래퍼 생성자에 대한 인수 전달을 지원해야 함을 의미합니다.
* 정의마다 여러 래퍼를 사용하여 작업합니다.
* 최소한 무슨 일이 일어나고 있는지 명확하게 해야 합니다. 새로운 사용자는 자신의 코드를 작성할 때 이를 무시해도 됩니다.
* "한 번 설명하면 기억하기 쉬운" 구문이어야 합니다.
* 향후 확장을 더 어렵게 만들지 마세요
* 입력하기 쉬워야 합니다. ; 이를 사용하는 프로그램은 이를 매우 자주 사용할 것으로 예상됩니다.
* 코드를 빠르게 검색하는 것이 더 어렵지는 않습니다. 그래도 모든 정의, 특정 정의 또는 함수가 허용하는 인수를 쉽게 검색할 수 있어야 합니다. 🎜> * 언어에 민감한 편집기 및 기타 "장난감 파서 도구 [12]"와 같은 보조 지원 도구를 불필요하게 복잡하게 만들지 마십시오.
* Python용 JIT 컴파일러가 출시되기를 바라면서 향후 컴파일러가 데코레이터에 맞게 최적화할 수 있습니다. 어느 시점에 존재하면 데코레이터의 구문이 함수 정의 앞에 와야 하는 경향이 있습니다.
* 현재 숨겨져 있는 함수의 끝에서 함수가 더 눈에 띄는 앞쪽으로 이동합니다. [13 ]