您的位置:首页 > 移动开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: