python3核心编程——装饰器
定义两个功能函数:
# -*- coding:utf-8 -*-
def foo(): # 打印"foo..."
print("foo...")
def bar(): # 打印"bar..."
print("bar...")
foo() # foo...
bar() # bar...
计算函数的运行时间,我们可以把函数改写为:
import time # 放在(文档)最顶端
def foo():
start = time.time() # 函数运行之前的时刻
print("foo...")
time.sleep(1) # 因为该程序运行时间太短,所以运用time.sleep()延长1s时间
end = time.time() # 函数运行完后的时刻
print(end - start) # 打印运行的时间
def bar():
start = time.time() # 函数运行之前的时刻
print("bar...")
time.sleep(1) # 因为该程序运行时间太短,所以运用time.sleep()延长1s时间
end = time.time() # 函数运行完后的时刻
print(end - start) # 打印运行的时间
foo()
# foo...
# 1.0006506443023682
bar()
# bar...
# 1.0007519721984863
通过在每个功能函数内部添加一些计算时间的代码,就能实现我们的需求,但是又出现了以下问题:
1、修改了功能函数本身(每次调用函数,都会打印运行的时间,如果有的时候,我不想打印呢?)。
2、代码量大,且重复(此处只有2个功能函数,我们可手动修改,如果有几十个,几百个,那岂不是要改到天手抽筋)。
所以,针对以上两点情况,及解决代码重复和不修改函数本身,我们可以新定义一个计算时间的函数:
import time
def foo(): # 打印"foo..."
print("foo...")
def bar(): # 打印"bar..."
print("bar...")
def caltime(func): # 计算函数运行的时间
start = time.time() # 函数运行之前的时刻
func()
time.sleep(1) # 因为该程序运行时间太短,所以运用time.sleep()延长1s时间
end = time.time() # 函数运行完后的时刻
print(end - start)
caltime(foo)
# foo...
# 1.0009233951568604
caltime(bar)
# bar...
# 1.0008749961853027
我们发现,通过新建一个函数来实现一个功能,很方便、简洁。但是这样,函数的调用方式却发生了改变,比如:
我们最开始调用功能函数是:foo() 。现在要计算函数运行时间,我们的调用方式是:caltime(foo) 。
我们需要达到的需求是:就最终执行foo(),就可实现该函数本身的功能和计算该函数运行的时间。而不是caltime(foo)。
如果我们的项目中调用了几十次foo函数,并且都需要计算时间,那我们岂不是也要挨个把foo()改成caltime(foo) ,其实这也是一件恼火的事情。所以我们得像个办法(就是还是书写foo()调用函数,但是同时可以计算运行的时间):
import time
def foo(): # 打印"foo..."
print("foo...")
def bar(): # 打印"bar..."
print("bar...")
def caltime(func):
def inner():
start = time.time()
func()
time.sleep(1)
end = time.time()
print(end - start)
return inner
foo = caltime(foo)
foo()
# foo...
# 1.0006935596466064
最后我们就是通过foo()而不是caltime(foo)来调用函数的。所以,我们就可通过把函数当作返回值传递,来实现最终的调用方式(调用函数时的书写方式)相同。
caltime(foo)的执行结果是,返回的inner函数(并不会执行inner函数),然后把这个inner函数赋值给foo(即foo=caltime(foo))。所以,foo()就相当于在执行inner()。
这里的caltime()就是装饰器,但是我们会发现,每次执行foo()之前,都会写上foo=caltime(foo),也挺麻烦的,所以装饰器更专业更优雅写法就是:
1、把装饰器caltime()写在功能函数前面;
2、把foo=caltime(foo)这句每次调用都会写(重复)的代码写成 @caltime 的方式,放到功能函数前面。
import time
def caltime(func):
def inner():
start = time.time()
func()
time.sleep(1)
end = time.time()
print(end - start)
return inner
@caltime # 此时caltime就相当于是foo=caltime(foo)
def foo(): # 打印"foo..."
print("foo...")
def bar(): # 打印"bar..."
print("bar...")
# foo = caltime(foo)
foo()
# foo...
# 1.000216007232666
end

浙公网安备 33010602011771号