视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
pythondecorators
2020-11-27 14:27:22 责编:小采
文档


Contains:

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]

下载本文
显示全文
专题