`

python decorators

阅读更多
Contains:
  • 1、decorators
  • 2、functools

首先我们看下tornado中使用的装饰器
1、@tornado.web.authenticated
引用
Decorate methods with this to require that the user be logged in.

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
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。
接下来,我们写个单利模式的装饰器:
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这个装饰器实现了类的单例模式,可以确保类只会被实例化一次。

使用装饰器对参数以及方法返回结果的验证方法:
#-*-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)


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]



参考资料:
http://www.python.org/dev/peps/pep-0318/
http://wiki.python.org/moin/PythonDecorators
http://wiki.python.org/moin/PythonDecoratorLibrary
http://blog.csdn.net/beckel/article/details/3585352
http://blog.csdn.net/beckel/article/details/3945147
http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
http://mrcoles.com/blog/3-decorator-examples-and-awesome-python/
http://stackoverflow.com/questions/308999/what-does-functools-wraps-do
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics