注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天地不仁,以万物为Googol!

天行有常,不以物喜,不以己悲……

 
 
 

日志

 
 

揭密Python的修饰(decorators)  

2008-03-31 23:12:07|  分类: 翻译 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

原文见:http://ipozgaj.blogspot.com/2008/03/python-decorators-demistified.html

如果你看过一些新潮的Python代码的话,你应该会注意到修饰的广泛应用。在Python的世界里,修饰是个相当新的概念,它第一次出现是在2.4版。修饰在很多情况下,可以帮你消除重复,写出更优雅的代码;不使用修饰来实现的话,很容易写出特别难看的垃圾。修饰在Python里是进行元编程的一种方法,比如,用来不修改函数体而增强一个已经存在的(被修饰的)函数的功能。

什么是修饰?让我首先给出一个可能在Python编程环境里是官方的定义。修饰是一个对象,其行为像是语法糖,用于修改一个函数或方法的表现。你可以通过下面的语法来识别修饰:

@<修饰名>
def <函数名>:
<函数体>

Python解释器暗中把上面的代码翻译成:

<函数名> = <修饰名> (<函数名>)

这里修饰仅仅起到封装现有函数的作用,但是一会儿我们将会看到,修饰还可以给函数增加新的功能。

虽然上面的例子仅仅给函数加了一个修饰,但实际不是这样,一个函数可以被多次修饰。使用多重修饰时,代码从下面的语法:

@<修饰1>
@<修饰2>
def <函数名>:
<函数体>

翻译成:

<函数名> = <修饰1>(<修饰2>(<函数名>))

以上的例子我们假设已经定义了修饰。不过在你的程序里,你需要先定义修饰,然后才能使用它。

让我们从最基础的例子开始。我们会修改一个求两个整数和的函数,让他返回一个16进制的结果,而不是默认的10进制:

def sum(a, b):
return a + b

现在让我们给它写一个修饰,而不是修改函数体。修饰函数以一个函数做输入参数,并返回一个新的函数来代替旧函数:

def hex(fn):
def new_fn(*args):
return "%x" % fn(*args)
return new_fn Return new_fn

在修饰体里,我们定义了一个新函数,,这个新函数会把所有参数读入到一个元组里(* args语法),之后使用被修饰的函数(fn)来计算结果。计算后的结果会被转化为16进制返回。现在,我们可以简洁的修饰任何一个返回整数的函数。只需要加上一个“@hex”就可以了:

>>> @hex
... def sum(a, b):
... return a + b
...
>>> sum(10,5)
'f'

修饰,和其他所有在Python里的东西一样,都是一格对象,因此我们可以做些更有趣的事情。比如,我们可以传参数给修饰(向修饰传递参数),来更加精确的定义输出结果。

在现实世界中,什么情况下可能用到修饰呢?假设你现在在开发一个多线程程序,并且你想用一种优雅的方法让一些在不同线程里的函数互斥执行。从本质上说,你想做的是串行两个或多个函数的执行过程,比如,在一些函数运行时,我们需要阻止另一些函数的执行。为了完成这件事,你可以在修饰内使用Python内建的可重入锁对象(threading.RLock)来阻止并发,并使用队列对象(collections.Queue)来记住哪些函数(或事务)需要在锁释放后被执行。

想了解更多关于修饰的内容,PEP 318是个很好的起点。

  评论这张
 
阅读(1030)| 评论(10)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017