没别的意思,稍微记录一下Python装饰器的简单理解
对Python语法尤其是对函数式编程不太熟悉的话可能理解Python的装饰器模式会比较费劲一点,这边简单理解一下Python中的装饰器是个什么东西。
首先,很重要的一点就是Python可以把函数当作对象引用一样传递,所以我们可以把函数当作参数传递给另一个函数,也可以把函数当作另一个函数的返回值,是不是感觉要上天?
加上()的话表示函数在这句代码执行的时候就调用了,不加则表示仅仅当作一个引用传递,并不调用
def func_a(func_r1, func_r2):
print func_r1()
return func_r2
def func_b():
return "hi,kyson.I am func b"
def func_c():
return "hi,kyson.I am func c"
if __name__ == '__main__':
print func_a(func_b, func_c)()
一开始看到上面这段的时候其实并没有多少感觉,但是我们只要稍微深究一下就会发现这里面其实可以做很多事情了。
我们可以想一个例子,比如:我现在想要设计一个函数,这个函数可以把其他函数的调用时间打印下来,我们把这个函数暂时命名为:time_cost。
用刚才的想法,我们只需要把任意函数当作参数传到time_cost,然后time_cost调用外部传进来的函数之前和之后计算一下时间,然后打印即可:
def time_cost2(func_r):
start = time.clock()
func_r()
end = time.clock()
print "cost: %.4f" % (end - start)
这样,我们就可以调用time_cost2函数,并传入真正想要调用的函数,就可以执行函数并打印执行消耗的时间了,cool~
到这里其实装饰器已经完成了,但是还不够。因为每次我们想调用函数的时候只能当作参数传给time_cost2,然后执行time_cost2,这样如果有很多函数需要调用,岂不是每次调用都要换成time_cost2?
这时候Python又露出了蜜汁笑容:不好意思,在我这儿函数名可以赋值给变量
那又怎样?
那就可以把time_cost2函数名称赋值给以真正的函数名称为变量名的变量了!(不好意思,其实很简单的一句话我解释不好)
看看代码吧,就容易理解了:
def time_cost2(func_r):
start = time.clock()
func_r()
end = time.clock()
print "cost: %.4f" % (end - start)
def func2():
time.sleep(3)
func2 = time_cost2(func2)
if __name__ == '__main__':
func2()
我在执行func2()的时候你猜怎么着?报错了!
Traceback (most recent call last):
File "D:/Dev/Python/Workspace/test/test.py", line 49, in <module>
func2()
TypeError: 'NoneType' object is not callable
会过来看看代码,原来func2在赋值的时候已经是time_cost2(func2)执行了的,所以func2就是time_cost2(func2)的返回值,而并不是可调用的函数,尴尬。
所以问题就变成了,我怎么样让time_cost2(func2)暂时先不执行,当作可调用的函数赋值给func2?
这时候文章开头提到的一点就很重要了:函数可以当作另一个函数的返回值。
所以这时候代码变成了这样:
def time_cost(func1):
def time_cost_wrap():
start = time.clock()
func1()
end = time.clock()
print "cost: %.4f" % (end - start)
return time_cost_wrap
def func():
time.sleep(3)
func = time_cost(func)
if __name__ == '__main__':
func()
time_cost函数里面定义了time_cost_wrap函数,这个函数做的事情就是刚才time_cost函数做的事情,然后time_cost返回了time_cost_wrap函数,这里注意是返回的函数名称,并没有执行time_cost_wrap,所以当我们把time_cost(func)赋值给func变量的时候,实际上我们是把time_cost_wrap函数赋值给了func,这时候我们再执行func()的时候就相当于执行了time_cost_wrap()。
Perfect.
完成代码:
# -*- coding:utf-8 -*-
import time
def func_a(func_r1, func_r2):
print func_r1()
return func_r2
def func_b():
return "hi,kyson.I am func b"
def func_c():
return "hi,kyson.I am func c"
def time_cost2(func_r):
start = time.clock()
func_r()
end = time.clock()
print "cost: %.4f" % (end - start)
def func2():
time.sleep(3)
func2 = time_cost2(func2)
def time_cost(func1):
def time_cost_wrap():
start = time.clock()
func1()
end = time.clock()
print "cost: %.4f" % (end - start)
return time_cost_wrap
def func():
time.sleep(3)
func = time_cost(func)
if __name__ == '__main__':
# print func_a(func_b,func_c)
# func2()
func()
网友评论