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作者: ...
随机推荐
-
#define用法解析
#define Add(a,b) a+b; 在一般使用的时候是没有问题的,但是如果遇到如: c * Add(a,b) * d 的时候就会出现问题,代数式的本意是a+b然后去和c,d相乘,但是因为使用了 ...
-
CoreGraphics相关方法
// 将view转为image(不经常用到的功能)(摘自SCCatWaitingHUD) - (UIImage *)convertViewToImage { CGSize s = self.bound ...
-
谷歌浏览器安装adblock广告屏蔽插件
访问不到google的应用商店的话,就从网上直接查找adblock for chrome.打开浏览器的开发者模式,下载解压后直接拖拽到浏览器即可.下载地址http://www.cr173.com/so ...
-
int型长度
Ø 基本数据类型 C语言中只有4中基本数据类型——整型.浮点型.指针和聚合类型(如数组和结构等):所有其他类型都是从这4种基本类型的某种变化或组合派生而来. 一.整型家族 整型家族包括char.sh ...
-
aspx后台生成json对象
json对象应用很广,有时,我们要把一些数据转化为json对象,就需要用到以下方法了. 1.使用Newtonsoft.Json.DLL (推荐使用) 下载地址:http://files.cnblogs ...
-
1632: [Usaco2007 Feb]Lilypad Pond
1632: [Usaco2007 Feb]Lilypad Pond Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 404 Solved: 118[Sub ...
-
JQuery代码实现上拉加载(不使用插件)
<script type="text/javascript"> $(window).scroll(function() { //已经滚动到上面的页面高度 var sl_ ...
-
作为小白,如何学习Web前端开发?
作为一个已经写码这么多年的人,我不会告诉你我最初的时候是自学的,因为刚开始自己学真的特别无聊枯燥,实在学不下去,所以就自己报了一个培训(上元教育)的地方,毕竟是交了钱的,本着不服气的精神,硬是把自己生 ...
-
Taro-ui TabBar组件使用路由跳转
1. 安装taro-ui (此处使用cnpm) cnpm install taro-ui 2. 全局引入样式 app.scss sass :@import "~taro-ui/dist/st ...
-
002_pip安装失败
一.安装cmdb的驱动遇到了如下问题 [root@localhost 003_pyenv]# pip2.7 install cmdb_sdk==0.3.1 -i http://cmdb.elenet. ...