

1、decorators
2、functools
首先我们看下tornado中使用的装饰器
1、@tornado.web.authenticated
引用
Decorate methods with this to require that the user be logged in.
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就ok了。
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
result is :
<__main__.Foo instance at 0x103152c20> <__main__.Foo instance at 0x103152c20> True
<__main__.Bar instance at 0x103152c68> <__main__.Bar instance at 0x103152cb0> 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)
result:
assert a > 100000,"arg %r must gt 100000" % a
AssertionError: arg 5000 must gt 100000
引用
Design Goals:
The new syntax should
* work for arbitrary wrappers, including user-defined callables and the existing builtins classmethod() and staticmethod(). This requirement also means that a decorator syntax must support passing arguments to the wrapper constructor
* work with multiple wrappers per definition
* make it obvious what is happening; at the very least it should be obvious that new users can safely ignore it when writing their own code
* be a syntax "that ... [is] easy to remember once explained"
* not make future extensions more difficult
* be easy to type; programs that use it are expected to use it very frequently
* not make it more difficult to scan through code quickly. It should still be easy to search for all definitions, a particular definition, or the arguments that a function accepts
* not needlessly complicate secondary support tools such as language-sensitive editors and other "toy parser tools out there [12]"
* allow future compilers to optimize for decorators. With the hope of a JIT compiler for Python coming into existence at some point this tends to require the syntax for decorators to come before the function definition
* move from the end of the function, where it's currently hidden, to the front where it is more in your face [13]
