本节内容
高阶函数
返回函数
匿名函数
装饰器
一、高阶函数
高阶函数:能把函数做为参数传入的函数
变量可以指向函数
print(abs(-10)) a=abs print(a(-10)) 10 10
函数本身也可以赋值给变量,即:变量可以指向函数
那么函数名是什么呢?函数名其实就是指向函数的变量!对于abs()
这个函数,完全可以把函数名abs
看成变量,它指向一个可以计算绝对值的函数!
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
Python内建了map()
和reduce()
函数。
map()函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
def f(x): return x*x m=map(f,[1,2,3,4,5]) print(list(m)
Python内建的filter()
函数用于过滤序列
和map()
类似,filter()
也接收一个函数和一个序列。和map()
不同的是,filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素。
在一个list中,删掉偶数,只保留奇数
def is_odd(n): return n % 2 == 1 h=list(filter(is_odd,[1,2,3,4,5,6,7,8])) print(h)
注意到filter()
函数返回的是一个Iterator
,也就是一个惰性序列,所以要强迫filter()
完成计算结果,需要用list()
函数获得所有结果并返回list
Python内置的sorted()
函数就可以对list进行排序
c=sorted([10,-20,30,40,4]) print(c) [-20, 4, 10, 30, 40]
sorted()函数也是一个高阶函数,它还可以接收一个key
函数来实现自定义的排序
按照绝对值排序
d=sorted([10,-20,30,40,4],key=abs) print(d) [4, 10, -20, 30, 40]
二、返回函数
函数作为返回值
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回
def f(): print('call f') # 定义函数 h def h(): print("call h") # 返回函数 h return h
函数的调用过程:
def f(): print('call f') # 定义函数 h def h(): print("call h") # 返回函数 h return h x=f() print(x) x() call f <function f.<locals>.h at 0x0000025A6E28FAE8> call h
只返回函数的作用:
返回函数可以把一些计算延迟执行。
一个函数可以返回一个计算结果,也可以返回一个函数。
返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。
三、匿名函数
当我们在传入函数时,可能我们这个函数只使用一次,那么我们就没有必要去定义一个函数了,可以使用匿名函数。
关键字lambda
表示匿名函数
匿名函数有个限制,就是只能有一个表达式,不用写return
,返回值就是该表达式的结果
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
f=map(lambda x:x*x,[1,2,3,4,5,6]) print(list(f))
[1, 4, 9, 16, 25, 36]
k=lambda x:x*x f=map(k,[1,2,3,4,5,6]) print(list(f)) [1, 4, 9, 16, 25, 36]
也可以把匿名函数作为返回值返回
def build(x, y): return lambda: x * x + y * y
四、装饰器
在代码运行期间动态添加功能的方式称之为“装饰器”(Decorator)
通俗来说装饰器就是为其他的函数来添加附加功能。
装饰器本质还是一个函数。
装饰器需要的知识:
函数即 变量
高阶函数
嵌套函数
装饰器的原则:
不修改被装饰的函数的源代码。
不能修改被装饰函数的调用方式。
装饰器要遵守者2个原则。
函数及变量
# 函数及变量 print(abs(-10)) # 可以将一个函数名赋值给一个变量 absfun=abs; print(absfun(-10)) 10 10
函数与变量在内存中如何存储的。
高阶函数:
高阶函数:可以接收一个函数名参数的函数 返回值中包含函数名的函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time # 计算函数的执行时间 def timeer(func): start=time.time() func() end=time.time(); print(end-start) def absfun(): time.sleep(3) print("absfun:is run") pass # 使用 timeer(absfun) absfun:is run 3.000668525695801
从上面者个例子中可以看出:我们在没有改变函数的源代码的条件下给原函数实现了一个计算函数运行时间的功能。但是我们改变了函数的调用方式。所以这不符合我们装饰器的原则。
那我们使用返回值的:
import time # 计算函数的执行时间 def timeer(func): start=time.time() func() end=time.time(); print(end-start) return func def absfun(): time.sleep(3) print("absfun:is run") pass # 使用 absfun=timeer(absfun) absfun()
你会发现我们的absfun函数执行了2次。但是你会发现我们的调用方式和我们常规的调用方式就一致了,这样可以满足装饰器的第2个原则:不改变调用方式。
嵌套函数:
嵌套函数指的是在函数内部定义一个函数,而不是调用。
函数只能调用和它同级别以及上级的变量或函数。也就是说:里面的能调用和它缩进一样的和他外部的,而内部的是无法调用的。
import time # 计算函数的执行时间 def timeer(func): def doce(): start=time.time() func() end=time.time(); print(end-start) return doce def absfun(): time.sleep(3) print("absfun:is run") pass # 使用 absfun=timeer(absfun) absfun()
从上面的代码中我们可以看出现在我们没有修改调用函数的方式,同时还实现了函数运行时间的计算功能。
但是实际上我们修改了调用方式。但在表面上并未修改调用方式,而且实现了附加功能
你会发现其实我们在调用之前实现了一步:absfun=timeer(absfun),那么我们只要在我们的每个需要装饰的函数执行之前执行一个absfun=timeer(absfun)就可以不用改变我们的函数调用方式,同时实现功能的附加。这样太麻烦,Python给我们提供了一种语法糖:@timeer :
@timeer=timeer(absfun) 这样我们就实现了装饰
真正的装饰器:没有参数的装饰器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time # 计算函数的执行时间 def timeer(func): def doce(): start=time.time() func() end=time.time(); print(end-start) return doce @timeer def absfun(): time.sleep(3) print("absfun:is run") pass # 使用 absfun()