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. bootstrap注意事项(二)

    1.内联子标题 在标题内还可以包含 <small> 标签或赋予 .small 类的元素,可以用来标记副标题. <!DOCTYPE html> <html> < ...

  2. JAVA GC之标记 第五节

    JAVA GC之标记  第五节 OK,我们继续昨天最后留下的问题,什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方 ...

  3. 剑指offier第4题

    /* 问题1:替换字符串,是在原来的字符串上做替换,还是新开辟一个字符串做替换! 问题2:在当前字符串替换,怎么替换才更有效率(不考虑java里现有的replace方法). 从前往后替换,后面的字符要 ...

  4. java打包/命令行方式运行jar(命令行进行程序测试)

    public class Testtmp { public static void main(String[] args) { // TODO Auto-generated method stub f ...

  5. Ubuntu下使用Vi时方向键变乱码 退格键不能使用的解决方法

    要在Ubuntu下编辑一些文件,这就涉及到了vi这个编辑器了.在Ubuntu下,初始使用vi的时候有点问题,就是在编辑模式下使用方向键的时候,并不会使光标移动,而是在命令行中出现[A [B [C [D ...

  6. weather compare

  7. atoi函数和atof函数

    1.函数名:atoi 功能:是把字符串转换成整型数的一个函数,应用在计算机程序和办公软件中 名字来源:alphanumeric to integer 用法:int atoi(const char *n ...

  8. MVC入门

    MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C 则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式.比如一批统计数据可以分别用柱状图.饼图 ...

  9. ElasticSearch Aggregation

    http://zaiste.net/2014/06/concisely_about_aggregations_in_elasticsearch/

  10. [LeetCode][Python]Regular Expression Matching

    # -*- coding: utf8 -*-'''https://oj.leetcode.com/problems/regular-expression-matching/ Implement reg ...