高阶函数
a: 把一个函数名当作实参传给另一个函数(在不修改被装饰函数源代码的状况下为其添加功能)
b: 返回值中包含函数名(不修改函数的调用方式)ide
# 如今写一个装饰器 # 两个函数都有本身的逻辑,可以实现本身的功能 # 写一个装饰器,统计函数运行时间 1-1 import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') # 统计test1 和 test2 的运行时间,可是前提是不能修改调用方式
1-1-1 # 如何不修改源代码,给 test1 新增一个功能? import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') # 写一个高阶函数 def deco(func): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) # 那么怎么用? # 为何 test1 不加括号,由于test1(),传入的是返回值结果 deco(test1) deco(test2) ---> in the test1 the func run time is 3.0043373107910156 in the test2 the func run time is 3.0002830028533936
1-1-2 # 1-1-1 修改了函数的调用方式 # 如何不修改函数的调用方式? # 第二类高阶函数,不改变函数的调用方式,在使用的时候就是 test1 = deco(test1) 这种方式 # 可是前提是 须要把函数修改为 用 return 返回函数名的 第二种形式的高阶函数 # 这样,test1 就能够获取 deco 的返回值,deco 的返回值就是 test1 的 内存地址 # test1() 能够正常调用,test2()也能够 def deco(func): start_time = time.time() return func stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) import time def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') test1 = deco(test1) test1() test2 = deco(test2) test2() ---> in the test1 in the test2 # 没有修改函数的调用方式,也没有新增功能,什么都没有作 # 为何是这样呢? # 由于 deco 中的 return,直接调用了 test1; # 以后的内容不会执行,这就是 return 的一个特性
1-1-3 # 由于 1-1-2 中一直在用高阶函数,漏掉了嵌套 # 能够引入嵌套函数 def deco(func): start_time = time.time() return func stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) def timer(): def deco(): pass # 这是嵌套函数,如何把这个函数,融入到上面的 deco中呢?
1-1-4 import time def timer(func): # timer(test1) 把 test1 的内存地址 传给 func = test1 def deco(): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco # 返回 deco 函数的内存地址 # 这么作之后,用到了高阶函数,用到了函数嵌套 def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') timer(test1) print(timer(test1)) # 返回 deco 的内存地址 ---> <function timer.<locals>.deco at 0x000002C818B1D558>
1-2 # 想要调用 timer(test1) 应该怎么作? # 给它赋值,而后 test1 执行就能够 import time def timer(func): # timer(test1) 把 test1 的内存地址 传给 func = test1 def deco(): start_time = time.time() func() # run test1() stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco # 返回 deco 函数的内存地址 # 这么作之后,用到了高阶函数,用到了函数嵌套 def test1(): time.sleep(3) print('in the test1') def test2(): time.sleep(3) print('in the test2') test1=timer(test1) test1() # 这时候,test1 执行,其实是在执行 deco 函数,由于 timer 返回的是 deco;deco作的事情是计算时间; func 的值是 test1 的值 ---> in the test1 the func run time is 3.000483751296997 # 成功加了一个新功能,没有改变源代码和调用方式; # 用到函数的嵌套,引用高阶函数的定义,最终实现这样的效果
1-3 # 可是 1-2 那样 # test1=timer(test1) # test1() # 这种方式,有些麻烦;每次都须要运行装饰器,运行一个和原来函数名同样的东西 # 如何直接 test1() 运行呢? # 解释器提供了一种语法,直接加 @timer;@ 后加上装饰器的名字;写在想要新增功能的函数的头部 # @timer 就等同于 test1 = timer(test1) 这部操做 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 @timer def test1(): time.sleep(3) print('in the test1') @timer def test2(): time.sleep(3) print('in the test2') test1() test2() ---> in the test1 the func run time is 3.000530958175659 in the test2 the func run time is 3.000612497329712 # 这两个函数正常运行了,同时加上了新功能
1-1 # 若是 test2 里面有一个参数 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 @timer def test1(): time.sleep(3) print('in the test1') @timer def test2(name): print("test2:",name) test1() test2() ---> TypeError: test2() missing 1 required positional argument: 'name' # 结果是出错的,test2 缺乏位置参数 name # @timer 至关于 test2 = timer(test2) # test2 传到里面都作了什么? test2 → func → 执行 deco 因此,内嵌的deco函数,执行了吗? # return deco,直接返回了 deco 的内存地址 # test2 实际上是等于 deco,因而 test2()至关于 deco(),执行到 func()时,至关于执行到了 test2() # 可是 test2 是要求传参数的,test2()没有传参;因此会报错 # 那么,这种状况应该如何处理?如何把参数传进来?
1-2 # test2(name),其实就是至关于 deco(name) import time def timer(func): def deco(arg1): start_time = time.time() func(arg1) stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco @timer def test2(name): print("test2:",name) test2("alex") ---> test2: alex the func run time is 0.0
1-2-1 # 若是传入两个参数呢? # 要装饰的函数多是各类各样的功能 # 因此须要 *args **kwargs import time def timer(func): def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print("the func run time is %s" %(stop_time-start_time)) return deco @timer def test1(): time.sleep(3) print('in the test1') @timer def test2(name,age): print("test2:",name,age) test1() test2("alex",11) ---> in the test1 the func run time is 3.0008721351623535 test2: alex 11 the func run time is 0.0009975433349609375