python学习之路(九)

这一节主要讲的是装饰器。装饰器是一个非常好用的,用于装饰已有函数的函数功能。

 其优点是不用修改调用方式,还不用修改源代码。

他的思想是:函数既变量;高阶函数;嵌套函数。

 现在来尝试写装饰器

有两个函数 各自实现自己的功能 
每个函数执行的时候 都肯定要消耗时间
那现在 就写一个装饰器 来统计这两个函数的运行时间
 
首先 把这两个函数写好
python学习之路(九)
 
 要注意的是 不可以改变函数的调用方式
test1 函数的调用 —— test1()
test2 函数的调用 —— test2()
 
 怎样才能在不改变函数调用方式的前提下 给函数增加功能呢
首先 要搞一个高阶函数
然后 把函数传给高阶函数 当作参数
python学习之路(九)
 
这样子 运行效果:
python学习之路(九)
 
功能 是加上去了 但是 调用方式也改变了 这样不行
 
 高阶函数还没有用到呢
import time

def timer(func):
def deco():
start_time = time.time()
func()
stop_time = time.time()
print('----------the func run time is %s' %(stop_time-start_time))
return deco


def foo1():
time.sleep(1)
print('----------i am in foo 111----------')


def foo2():
time.sleep(2)
print('----------i am in foo 222----------')


foo1 = timer(foo1)
foo1()

foo2 = timer(foo2)
foo2()
高阶函数 就是在本来已经实现了功能的代码段外面 再套一层
 
本来实现计时功能的代码:
def deco(func):
start_time = time.time()
func()
stop_time = time.time()
print('----------the func run time is %s' %(stop_time-start_time))
外面套一层:
def timer(func):
def deco():
start_time = time.time()
func()
stop_time = time.time()
print('----------the func run time is %s' %(stop_time-start_time))
return deco
还有一种语法糖
比方说 timer 是实现了附加功能的代码:
def timer(func):
def deco():
start_time = time.time()
func()
stop_time = time.time()
print('----------the func run time is %s' %(stop_time-start_time))
return deco
那现在要给 foo1 函数增加功能 就这样:
@timer
def foo1():
time.sleep(1)
print('----------i am in foo 111----------')
要给 foo2 函数增加功能 就这样:
@timer
def foo2():
time.sleep(2)
print('----------i am in foo 222----------')
最后运行的时候 就像原先的调用方式一样就可以了
foo1()

foo2()
运行结果 功能加上了 同时函数调用方式没有变:
python学习之路(九)
 
7.7 调试方式运行
python学习之路(九)
先是导入模块:import time
然后走到下一行 timer 函数的定义:def timer(func):
(因为 python 它是解释执行 所以是按顺序一行一行去执行的)
 
再往下走:函数体没有执行 直接跳到语法糖:
python学习之路(九)
 
因为 def 里面的函数体 它只是一个定义 它没有调用 所以就不执行
 
然后再往下 从语法糖 直接跳到:foo1()
中间的 foo1 函数的定义也不执行 原理跟上面那个 timer 不执行一样
 
foo1() 这句是函数调用 这句调用直接引导到 deco 函数的定义
python学习之路(九)
 
这是为什么呢? —— 因为刚才运行语法糖的时候 它实际上运行的是:
foo1 = timer(foo1)
它实际上就是把 timer 函数 赋值给 foo1 这个变量
所以 foo1 已经被替换成了 timer 所以调用 foo1 的时候 会去执行 timer

然后蹦到 def deco() 的时候 它也是一个定义 没有调用 跟上面说过的那样
它不执行中间的函数体 直接跳到 return deco 返回了
python学习之路(九)
 
继续往下走 又走到了 foo1() 这次直接跳到了 deco 函数去执行它 
所以其实执行 test1 函数 就是执行 deco 函数
在执行 deco 函数的时候 先取了一个 start_time
然后执行 func() 函数
python学习之路(九)
 
执行 func() 函数 其实就是执行 foo1() 函数
这是因为 语法糖里面已经把 foo1 作为参数传给了 timer(func) 函数

执行 foo1() 函数 就是进入 foo1() 函数的函数体 
先睡 1 秒 然后 print 一行话
 
之后 再取一个 stop_time 然后再 print 一行话 结束