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

Decorators and Wrappers in Python的更多相关文章

  1. 我实在不懂Python的Asyncio

    原语 事件循环(Event Loop) Awaitables和Coroutines Coroutine Wrappers Awaitables and Futures Tasks Handles Ex ...

  2. Python装饰器完全解读

    1 引言 装饰器(Decorators)可能是Python中最难掌握的概念之一了,也是最具Pythonic特色的技巧,深入理解并应用装饰器,你会更加感慨——人生苦短,我用Python. 2 初步理解装 ...

  3. python问答

    1)什么是Python?使用Python有什么好处? Python是一种编程语言,包含对象,模块,线程,异常和自动内存管理.Python的好处在于它简单易用,可移植,可扩展,内置数据结构,并且它是一个 ...

  4. TensorFlow源码框架 杂记

    一.为什么我们需要使用线程池技术(ThreadPool) 线程:采用“即时创建,即时销毁”策略,即接受请求后,创建一个新的线程,执行任务,完毕后,线程退出: 线程池:应用软件启动后,立即创建一定数量的 ...

  5. Django—— 缓存框架

    译者注:1.无用的,吹嘘的说辞不翻译:2.意译,很多地方不准确. 动态网站最为重要的一点就是好,网页是动态的.每一次用户请求页面,网站就要进行各种计算——从数据库查询,到render模板,到各种逻辑运 ...

  6. Easy Install详细参数

    Easy Install Easy Install is a python module (easy_install) bundled with setuptools that lets you au ...

  7. 使用Django.core.cache操作Memcached导致性能不稳定的分析过程

    使用Django.core.cache操作Memcached导致性能不稳定的分析过程 最近测试一项目,用到了Nginx缓存服务,那可真是快啊!2Gb带宽都轻易耗尽. 不过Api接口无法简单使用Ngin ...

  8. CentOS安全防护实例

    (1) 借助iptables的recent模块限制IP连接数 可以限制瞬间连接数过大的恶意IP(比如web应用防护,但不适用于LVS+Keepalived集群环境) 防护指令如下 # 允许一个客户端6 ...

  9. 【译】PEP 318--函数和方法的装饰器

    PEP原文 : https://www.python.org/dev/peps/pep-0318 PEP标题: Decorators for Functions and Methods PEP作者: ...

随机推荐

  1. input type=button设置高度不管用

    <input type="button" name="calRate" id="calRate" value="查询&quo ...

  2. struts2中的表达元素标签使用详解

    级联标签是使用:一级下拉框应该使用map对象的key集合作为下拉框元素,二级下了框应该使用一级下拉框对应的选择值自动的弹出待选择的元素值(集合) 页面代码如下:<s:set name=" ...

  3. 解决eclipse创建Maven项目后无法生成src/main/java资源文件夹的方法

    在项目上右键选择properties,然后点击java build path,在Librarys下,编辑JRE System Library,选择workspace default jre.

  4. In-System Debugger for 8051 Devices(ISD 8051单片机在线调试器)

    此文档包含了最新版本的说明及最近的更新特别是对 ISD51 的说明(用户手册没有此说明) Keil Software,Inc and Keil Elektronik GmbH保留所有此文件中涉及的信息 ...

  5. UI设计中与字号有关的知识

    在我们设计APP.设计前端页面时,免不了要和各种文字大小打交道.字体的大小有多种单位,不明究里的话使用起来很容易出问题.今天整理了这方面的东西做了个图片,方便查看. 图上的资料来自互联网,感谢大家的负 ...

  6. Unix/Linux环境C编程入门教程(9) unbntu CCPP开发环境搭建

    1.      首先启动VMware,如果没有安装,请查看前面VMware的安装视频 2 启动虚拟机向导,选择自定义 3 单击下一步 4 选择稍后安装操作系统 5 .选择unbntu 64linux ...

  7. C# 多线程使用队列注意事项

    问题: 多线程运行时死亡机问题很频繁! 推理: 看源码推理,发现 Queue<T>这样的泛型不是线程安全的. 验证: 将 Queue<T> 换成 Queue 类,并以 lock ...

  8. C,C++经典(程序、错误程序)

    1,程序 未执行完错误的return 0

  9. JavaScript常用内置对象(window、document、form对象)

    由于刚开始学习B/S编程,下面对各种脚本语言有一个宏观的简单认识. 脚本语言(JavaScript,Vbscript,JScript等)介于HTML和C,C++,Java,C#等编程语言之间.它的优势 ...

  10. POJ 3831 &amp; HDU 3264 Open-air shopping malls(几何)

    题目链接: POJ:id=3831" target="_blank">http://poj.org/problem?id=3831 HDU:http://acm.h ...