zoukankan      html  css  js  c++  java
  • Decorators and Wrappers in Python

    python代码一贯以优雅,简洁著称,而有时侯反而会让人难以理解,比如说wrapper(或者说decorator),这种方式提高了代码的可重用性,使用起来更简洁方便。

    举个例子,比如WebApp常用的处理请求的Handler。

    def show_page(request):
        # do something
        return response

    有些时候,如果请求是POST方式发送过来的,可能你需要检查用户名和密码的合法性。这个时候,你不得不修改以上函数来做必要的认证处理:

    def show_page(request):
        authenticator.authenticate(request)
        # do stuff
        return response

    但是这样做后,你发现你不想将代码植入到已经编好的功能中,因为那样做很stupid,如果每个需要认证的的地方都这样做,许多编号的handler都将改写。这似乎违背了代码的reusable。再者,从功能模块角度来看,认证似乎是一个辅助功能,不应该集成到Handler中。于是乎,使用decorators(或 wrappers)是一个不错的选择:

    @authenticate
    def show_page(request):
        # do stuff
        return response

    一个简单的authentiate如下:

    def authenticate(func):
        def authenticate_and_call(*args, **kwargs):
            if not Account.is_authentic(request): 
                raise Exception('Authentication Failed.')
            return func(*args, **kwargs)
        return authenticate_and_call

    经过@authenticate处理后的show_page(request)函数等价于如下:

    show_page = authenticate(show_page)

    从上面的函数也可直观的看出为什么decorator又叫做wrapper了,很直观的类似包装了一层东西一样,升级为2.0版本。

    python是函数式编程语言,函数可以作为参数传递或返回值返回。对于authenticate函数,在传入show_page后返回一个函数authenticate_and_call,也就是说show_page被重新指向了authenticate_and_call。

    show_page = authenticate(*args, **kwargs)

    这样一来,show_page加入了新的功能,完成了包装。他还是可以接收request参数,因为其参数是(*args, **kwargs)。

    此处顺便提一下python的 *args参数,看下面例子:

    def func1(x, y, z):
        print x
        print y 
        print z                 
    
    def func2(*args):
        # Convert args tuple to a list so we can modify it
        args = list(args)
        args[0] = 'Hello'
        args[1] = 'awesome'
        func1(*args)
    
    func2('Goodbye', 'cruel', 'world!')
    # Will print
    # > Hello
    # > awesome
    # > world!

    python中有很多库函数和自带函数参数中都包含*args, **kwargs,传递过来时就像一个"pack",而对于接收的函数来说可以"unpack"这些参数,做一些处理,例如:

    1. validate arguments before passing them on
    2. set defaults for positional arguments
    3. create adaptors for different pieces of code / libraries
    4. modify arguments depending on context
    5. log calls to methods
    6. write better and more resilient wrapper

    将参数定义为“任意”的方式在decorator中很常用。

    参考资料:

    http://hangar.herokuapp.com/python/packing-unpacking-arguments

    http://hangar.runway7.net/python/decorators-and-wrappers

  • 相关阅读:
    【转】ASP.NET页面刷新方法总结
    GridView点击超链接时弹出小窗口
    VS2008增加AJAX Control Toolkit3.5支持(组图)
    水晶报表中"已达到系统管理员配置的最大报表处理作业数限制"错误的处理
    asp.net 在使用Response.Redirect try{}catch{}块失效
    【转】ASP.NET的五大数据控件浅谈
    ASP.NET生成随机密码
    ASP.NET Web应用程序和ASP.NET网站的区别
    使用ArcGIS GP服务之一框架介绍
    mysql索引的类型和优缺点
  • 原文地址:https://www.cnblogs.com/vin-yuan/p/4812908.html
Copyright © 2011-2022 走看看