python decorators

巴扎黑
巴扎黑original
2016-12-09 13:31:331291parcourir

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 : 
8a6b224b078d998433cded93a760c0c9 8a6b224b078d998433cded93a760c0c9 True 
edce405bd80affddfe35e5f5ee52d00b a1bc37471b8040d27d3b369e4ed7758e 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]


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:python tipsArticle suivant:Python异步网络探