python学习之路(九)
这一节主要讲的是装饰器。装饰器是一个非常好用的,用于装饰已有函数的函数功能。
其优点是不用修改调用方式,还不用修改源代码。
他的思想是:函数既变量;高阶函数;嵌套函数。
现在来尝试写装饰器
有两个函数 各自实现自己的功能
每个函数执行的时候 都肯定要消耗时间
那现在 就写一个装饰器 来统计这两个函数的运行时间
首先 把这两个函数写好
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img0.ph.126.net/b6y87IjDZ-SdpiZlLWLX0A==/6631984758399977556.png)
要注意的是 不可以改变函数的调用方式
test1 函数的调用 —— test1()
test2 函数的调用 —— test2()
怎样才能在不改变函数调用方式的前提下 给函数增加功能呢
首先 要搞一个高阶函数
然后 把函数传给高阶函数 当作参数
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img1.ph.126.net/gLV6eiIuzoFRPRIRWumwRQ==/6631960569144158791.png)
这样子 运行效果:
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img1.ph.126.net/0qN-XQ0dXfOfd6ibnyTz6w==/6632214556330208494.png)
功能 是加上去了 但是 调用方式也改变了 这样不行
高阶函数还没有用到呢
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()
运行结果 功能加上了 同时函数调用方式没有变:
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img0.ph.126.net/4fA6i7CCKNPdkqkjWeVswg==/6632376184536764880.png)
7.7 调试方式运行
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img1.ph.126.net/ivR56sdyY2wXv3CODR0A2A==/6632036435446494754.png)
先是导入模块:import time
然后走到下一行 timer 函数的定义:def timer(func):
(因为 python 它是解释执行 所以是按顺序一行一行去执行的)
再往下走:函数体没有执行 直接跳到语法糖:
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img1.ph.126.net/JHEghu1uGWTKk3Po40JCFQ==/6632152983679032880.png)
因为 def 里面的函数体 它只是一个定义 它没有调用 所以就不执行
然后再往下 从语法糖 直接跳到:foo1()
中间的 foo1 函数的定义也不执行 原理跟上面那个 timer 不执行一样
foo1() 这句是函数调用 这句调用直接引导到 deco 函数的定义
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img2.ph.126.net/eiui67Z1RnaBGsFAaoPWxA==/6632381682094917482.png)
这是为什么呢? —— 因为刚才运行语法糖的时候 它实际上运行的是:
foo1 = timer(foo1)
它实际上就是把 timer 函数 赋值给 foo1 这个变量
所以 foo1 已经被替换成了 timer 所以调用 foo1 的时候 会去执行 timer
然后蹦到 def deco() 的时候 它也是一个定义 没有调用 跟上面说过的那样
它不执行中间的函数体 直接跳到 return deco 返回了
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img1.ph.126.net/yf8cj0QW14e5gxM4fMpUOA==/6632465244978652324.png)
继续往下走 又走到了 foo1() 这次直接跳到了 deco 函数去执行它
所以其实执行 test1 函数 就是执行 deco 函数
在执行 deco 函数的时候 先取了一个 start_time
然后执行 func() 函数
![第二阶段 7 装饰器小高潮 - Lucia - Lucias WorkShop](http://img1.ph.126.net/URxuVANOEKzva0zAOKnbbg==/6632600484908869219.png)
执行 func() 函数 其实就是执行 foo1() 函数
这是因为 语法糖里面已经把 foo1 作为参数传给了 timer(func) 函数
执行 foo1() 函数 就是进入 foo1() 函数的函数体
先睡 1 秒 然后 print 一行话
之后 再取一个 stop_time 然后再 print 一行话 结束