装饰器——高阶函数
高阶函数分为两种:
a:把一个函数名当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加附加功能)
b: 返回值中包含函数名(不修改函数的调用方式)
a:
第一个代码:
def bar():
print('in the bar')
def test1(func):
func()
test1(bar)
如何理解这一串函数:首先定义了bar这个函数,然后定义了func这个函数,相当于2个门牌号。然后test1(bar)相当于令bar=func,这时候第四行就相当于bar(),因此就print('in the bar')。
更复杂的第二个代码:
import time 1
def bar(): 2
time.sleep(3) 3
print('in the bar') 4
print(bar) 5
def test1(func): 6
start_time=time.time() 7
func() 8
stop_time=time.time() 9
print("the func run time is %s"%(stop_time-start_time)) 10
test1(bar) 11
如何理解:首先定义了bar函数,后面2行代码是这个函数的逻辑,相当于创建了一个小房子,这个小房子里面是这个代码的逻辑,然后bar是这个房子的门牌号。所以如果bar(),就相当于运行下面2行代码,但是如果bar其实就是这个门牌号的位置,所以print(bar)相当于将bar的内存位置print出来。
然后定义了func这个函数,下面4行是他的逻辑。所以,test1(bar),其实是令bar=func,然后程序到第6行,记录下来开始的时间,然后func()其实就是bar(),所以这时候代码跑到了第三行,睡了3秒,然后print('in the bar'),然后到了第九行记录下来结束的时间,最后再执行第10行。
b:
1. import time
2. def bar():
3. time.sleep(3)
4. print('in the bar')
5. def test2(func):
6. print(func)
7. return func
8. print(test2(bar))
9. bar=test2(bar)
10. bar()
首先定义了bar这个函数,我们想要装饰这个函数,因此有了下面test这个函数,首先第八行,bar=test2(bar),test2(bar),其实是将bar赋值给func,而bar是一个内存地址,所以他是将bar的内存地址给了func,然后print出bar的内存地址,然后返回到func因此test2(bar)依旧是bar的内存地址,所以 print(test2(bar))其实是又将bar的内存地址打印了一边。然后令bar=test2(bar),其实是令bar等于这个内存地址,然后运行bar()其实既运行了test2(),也运行了bar()。
这其实就是装饰器的作用,假如说修改之前没有5 6 7 8这4行,我们现在重新定义了test2这个函数, 6 7是其想实现的功能,我们这时候是不是就没有改变bar的源代码,也没有改变他的调用方式。这就是,装饰器中的高阶函数。