当前位置:Gxlcms > Python > pythondecorators

pythondecorators

时间:2021-07-01 10:21:17 帮助过:32人阅读

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]

人气教程排行