花了很长时间理解清楚什么是装饰器,是不是我太笨了,果真今天没心情学习....
于是,我找了另外的教程去深刻理解什么是装饰器。
其实,简单说装饰器的作用是:定义了一个函数,运行时动态为函数增加功能,但是不想改变函数代码
是不是还是有些难以理解,那我们就来看一个循序渐进的例子!
装饰器的定义对于我而言,很难一下子就理解,于是来看一个小例子:
def foo():
print 'in foo()'
foo()
这是一个很无聊的函数,但是如果想看看执行这个函数用了多长时间......那么我们可以这样做:
import time
def foo():
start = time.clock()
print 'in foo()'
end = time.clock()
print 'used:', end - start
foo()
上述函数实现了需求。可是如果对另一个叫foo2的函数产生了更浓厚的兴趣,怎么办呢?如果把以上新增加的代码复制到foo2里,那如果还想看更多的函数,难道一直复制??
我们可以考虑重新定义一个函数timeit,将foo的引用传递给他,然后在timeit中调用foo并进行计时,这样,我们就达到了不改动foo定义的目的,而且,想看多少个函数,我们都不用去修改函数定义了!
import time
def foo():
print 'in foo()'
def timeit(func):
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
timeit(foo)
这时候问题来了,我们似乎修改了调用部分的代码。原本我们是这样调用的:foo(),修改以后变成了:timeit(foo)。这样的话,如果foo在N处都被调用了,你就不得不去修改这N处的代码。
既然如此,我们就来想想办法不修改调用的代码;如果不修改调用代码,也就意味着调用foo()需要产生调用timeit(foo)的效果。我们可以想到将timeit赋值给foo,但是timeit似乎带有一个参数……想办法把参数统一吧!如果timeit(foo)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数的话……就很好办了,将timeit(foo)的返回值赋值给foo,然后,调用foo()的代码完全不用修改!
#-*- coding: UTF-8 -*-
import time
def foo():
print 'in foo()'
# 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法
def timeit(func):
# 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
# 将包装后的函数返回
return wrapper
foo = timeit(foo)
foo()
这样,一个简易的计时器就做好了!我们只需要在定义foo以后调用foo之前,加上foo = timeit(foo),就可以达到计时的目的,这也就是装饰器的概念,看起来像是foo被timeit装饰了。
上面这段代码看起来似乎已经不能再精简了,Python于是提供了一个语法来降低字符输入量。
import time
def timeit(func):
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper
@timeit
def foo():
print 'in foo()'
foo()
重点关注@timeit,在定义上加上这一行与另外写foo = timeit(foo)完全等价,千万不要以为@有另外的魔力。除了字符输入少了一些,还有一个额外的好处:这样看上去更有装饰器的感觉。
这样去讲装饰器是不是更加的清晰了,彻底理解!!!
明天发总结的装饰器的各种用法!!!
网友评论