Decorators and Wrappers in Python
2015-09-16 12:06
316 查看
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
相关文章推荐
- Swift学习笔记(二十七)——条件语句和Switch-case语句
- Android多线程通信之Handler
- iOS-细节小结
- Android 不要把android做成ios!
- Cocos2d-x开发中Ref内存管理
- 为UIWebView实现离线浏览
- 安卓判断APP是运行在前台还是后台
- android开发不继承ActionBarActivity直接继承Activity的方法
- 进程&线程-ios
- android选择图片进行裁剪
- block的实质
- Android Studio Tips & Tricks: Moving Around
- object- c 字符串操作
- iOS 警告收录及科学快速的消除方法
- IOS 开发文件操作——NSFileManager
- Unity3D教程宝典之 FX Maker
- Android四大基本组件介绍与生命周期
- Android列表对话框用法实例分析
- C# Object.MemberwiseClone 方法
- android 系统优化包括哪些方面