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"这些参数,做一些处理,例如:
- validate arguments before passing them on
- set defaults for positional arguments
- create adaptors for different pieces of code / libraries
- modify arguments depending on context
- log calls to methods
- 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的更多相关文章
- 我实在不懂Python的Asyncio
原语 事件循环(Event Loop) Awaitables和Coroutines Coroutine Wrappers Awaitables and Futures Tasks Handles Ex ...
- Python装饰器完全解读
1 引言 装饰器(Decorators)可能是Python中最难掌握的概念之一了,也是最具Pythonic特色的技巧,深入理解并应用装饰器,你会更加感慨——人生苦短,我用Python. 2 初步理解装 ...
- python问答
1)什么是Python?使用Python有什么好处? Python是一种编程语言,包含对象,模块,线程,异常和自动内存管理.Python的好处在于它简单易用,可移植,可扩展,内置数据结构,并且它是一个 ...
- TensorFlow源码框架 杂记
一.为什么我们需要使用线程池技术(ThreadPool) 线程:采用“即时创建,即时销毁”策略,即接受请求后,创建一个新的线程,执行任务,完毕后,线程退出: 线程池:应用软件启动后,立即创建一定数量的 ...
- Django—— 缓存框架
译者注:1.无用的,吹嘘的说辞不翻译:2.意译,很多地方不准确. 动态网站最为重要的一点就是好,网页是动态的.每一次用户请求页面,网站就要进行各种计算——从数据库查询,到render模板,到各种逻辑运 ...
- Easy Install详细参数
Easy Install Easy Install is a python module (easy_install) bundled with setuptools that lets you au ...
- 使用Django.core.cache操作Memcached导致性能不稳定的分析过程
使用Django.core.cache操作Memcached导致性能不稳定的分析过程 最近测试一项目,用到了Nginx缓存服务,那可真是快啊!2Gb带宽都轻易耗尽. 不过Api接口无法简单使用Ngin ...
- CentOS安全防护实例
(1) 借助iptables的recent模块限制IP连接数 可以限制瞬间连接数过大的恶意IP(比如web应用防护,但不适用于LVS+Keepalived集群环境) 防护指令如下 # 允许一个客户端6 ...
- 【译】PEP 318--函数和方法的装饰器
PEP原文 : https://www.python.org/dev/peps/pep-0318 PEP标题: Decorators for Functions and Methods PEP作者: ...
随机推荐
- MySQL数据库mysqlcheck的使用方法
MySQL数据库mysqlcheck的使用方法的相关知识是本文我们主要要介绍的内容,我们知道,mysqlcheck,是mysql自带的可以检查和修复MyISAM表,并且它还可以优化和分析表,mysql ...
- CentOS yum安装配置lnmp服务器(Nginx+PHP+MySQL)
1.配置防火墙,开启80端口.3306端口 vi /etc/sysconfig/iptables-A INPUT -m state --state NEW -m tcp -p tcp --dport ...
- PHP中mktime() 函数对于日期运算和验证
mktime() 函数对于日期运算和验证非常有用.它可以自动校正越界的输入: // 语法:mktime(hour,minute,second,month,day,year) echo(date('Y- ...
- Grunt之学习历程(转自网上资源-整理自用)
认识Grunt Grunt中文文档 安装Node环境 CNode 配置Grunt Grunt中文文档-配置任务 什么是package.json package.json中文文档 关于Grunt资料 应 ...
- 解析:用 CSS3 和 JavaScript 制作径向动画菜单
原作者的解析(英文):http://creative-punch.net/2014/02/making-animated-radial-menu-css3-javascript/ 原作者的解析(译文) ...
- 定时自动备份mysql数据库
新建备份文件并赋予可以执行的权限 mkdir -p /home/mysql_backup/ touch /home/mysql_backup/mysql_backup.sh chmod 551 /ho ...
- c语言:从一组数据中选出可以组成三角形并且周长最长的三个数(简单)
题目如下: 思路分析: 写出完整的程序: /* 问题描述: 有n根棍子,棍子i的长度为ai.想要从中选出3根棍子组成周长尽可能长的三角形.请输 出最大的周长,若无法组成三角形则输出0. */ #inc ...
- SQL Server 向堆表中插入数据的过程
堆表中 IAM 记录着的数据页,表的各个数据页之间没有联系.也就是说一个页面它不会知道自己的前一页是谁,也不知道自己的后一页是谁. 插入数据时先找到IAM页,再由pfs(page free spac ...
- [方法] ubuntu12.04开启root账户
ubuntu 12.04使用LightDM显示管理器,默认禁止root账户登录. 通过修改/etc/lightdm/lightdm.con文件可以打开root登录权限. 方法很简单,只要在lightd ...
- rsyslog ~ 波浪号
<pre name="code" class="html">Using negation can be useful if you would li ...