欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

python decorators

程序员文章站 2022-04-10 18:02:09
...
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]