关于Python 的@操作符 Decorator 的用法

原帖转自
http://blog.sina.com.cn/s/blog_571b19a001013h7j.html

直接翻译过来应该叫做 装饰符吧,不知是不是python特有的用法,看了下说明,艰难的弄明白了一些运作的原理。

简单的说,@操作符是用来提供调用的,光是说明可能无法理解,写了一个小小的例子:

def f1(arg):
    print ("f1")
    rl = arg()
    print (rl)
    return rl + "f1"

@f1
def f2(arg = ""):
    print ("f2")
    return arg + "f2r"

print ("start")
print (f2)
#print f2("1") 出错
#print f1(None)

这个例子是我自己一边改一边写的,和想像中有很大的区别,不过倒是认为完美的解释了这个操作符的原理:

以上语句在运行会输出
f1
f2
f2r
start
f2rf1

按ptyhon自带说明, 这里@符作符相当于 f1(f2()) 。但是从输出可以看出,这个运算其实在开始 import 时就已经在执行了,这也就是 f1 f2 f2r这几行会在 start 之前就出现的原因。而当运行到代码时,其实 f2函数已经不存在了, f2 在这里已经变成一个字符串了, 这就是后面 #print f2(“1”) 会出错的原因
也就是说,实际上前面那些个 @ 操作符完成了这么一个操作:
f2 = f1(f2())
f2已经被覆盖为 f1(f2) 的返回值了。运行时f2的结果已经固化,使用参数也不会重新计算,或者说根本无法使用参数。

当然原理如此,如果真的这么用,这东西当然就没有多少用处了。
但是我们假如定义一个类作为 装饰符 的话。

class myDecorator(object):

    def __init__(self, f):
        print ("inside myDecorator.__init__()")
        self.f = f

    def __call__(self):
        print ("inside myDecorator.__call__()")
        self.f()

@myDecorator
def aFunction():
    print ("inside aFunction()")

print ("Finished decorating aFunction()")

aFunction()

运行得到如下结果:

inside myDecorator.__init__()
Finished decorating aFunction()
inside myDecorator.__call__()
inside aFunction()

以上,初始化时 aFunction 会变成myDecorator类的一个实例,通过重载()操作符的办法,这样子aFunction实际上就变成了myDecorator.()操作了。于是从外型上看,这还是一个普通的函数的调用,但其实暗地里你可以做出很多不为人知的操作的……。

或者如果不想使用类,也可以使用内部函数的办法。如下的代码和上面的同样的效果

def entryExit(f):
    def new_f():
        print ("Entering", f.__name__)
        f()
        print ("Exited", f.__name__)
    return new_f

@entryExit
def func1():
    print ("inside func1()")

理论知道了,扩展开来,这东西能用来做什么呢?好吧,只有想不到的,没有做不到的。
以下页面列出了很多用这东西做出来的功能
http://wiki.python.org/moin/PythonDecoratorLibrary
比如:记忆函数,cached,自动为类加上属性,输出函数的参数,性能分析器,同步,替换函数的实现,状态机(同样的函数调用会产生不同的结果,甚至会调用完全不相干的代码)……
我认为其中最好的一个实现就是这个 Another Retrying Decorator ,一个可以对函数进行自动延时重试,并忽略掉指定异常的函数。
在网络操作中经常需要处理各种异常,并且需要进行重试的,现在只要在想要这么做的函数前加上 @retries(3) 就完美的解决了,连代码都不需改,真的是太方便了。
好了,到这里你应该能看明白那些经常见到的奇怪操作
@property
@classmethod
@staticmethod

的运行原理了吧。

参考资料:
python @ symbol

http://www.artima.com/weblogs/viewpost.jsp?thread=240808
Decorators I: Introduction to Python Decorators

http://wiki.python.org/moin/PythonDecoratorLibrary
PythonDecoratorLibrary

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值