python 高阶函数
修饰器
之前我一直有一个疑惑,就是修饰器里面对函数的操作为什么不能直接写进函数里面就好了吗?何必这么麻烦呢,当我进一步理解之后,原来修饰器的作用就是完成那些不能写进函数里面的功能的,好比必须要等到函数完成后的一些操作一样,(那么函数完成之前的工作怎么办呢?)
之前的学习笔记:https://www.cnblogs.com/Gaoqiking/p/10470407.html
使用高阶函数不要忘记
from functools import map
map/reduce
能够将函数的参数一下传进去,他能按顺序每次调用几个去自动执行完所有的,使用map记得在函数和iterable中加逗号
map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算
注意:
reduce( )中的序列不能为空
from functools import reduce def product(x, *y): return x * reduce(lambda a,b:a*b,y) product(5) #报错 Traceback (most recent call last): File "C:\Users\ADMINI~1.SC-\AppData\Local\Temp\learn_python_w11zu113_py\test_7.py", line 8, in <module> print('product(5) =', product(5)) File "C:\Users\ADMINI~1.SC-\AppData\Local\Temp\learn_python_w11zu113_py\test_7.py", line 5, in product return x * reduce(lambda a,b:a*b,y) TypeError: reduce() of empty sequence with no initial value #正确的 from functools import reduce def product(x, *y): if len(y)==0: return x else: return x * reduce(lambda a,b:a*b,y) #结果 5
参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317852443934a86aa5bb5ea47fbbd5f35282b331335000
过滤器filter
参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431821084171d2e0f22e7cc24305ae03aa0214d0ef29000
用于过滤序列,接受一个函数和一个序列,通过判断函数的返回值是False或者True来判断是否保留元素,把所有保留的元素作为一个新序列返回
作者举得例子当中,
def not_empty(s): return s and s.strip()#我开始觉得可以直接返回s.strip(),后来发现这样不能处理None,然后我不知道这个s and s.strip()是什么意思 list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) # 结果: ['A', 'B', 'C'] #如果其中有None、或者空’‘ 就返回None或者’‘ >>> None and '' >>> None and ' a' >>> '' and 'a' '' #其他就返回后面的那个 >>> 'a' and 'b' 'b' >>> 'b' and 'a' 'a' >>>
用filter()
这个高阶函数,关键在于正确实现一个“筛选”函数。
注意到filter()
函数返回的是一个Iterator
,也就是一个惰性序列,所以要强迫filter()
完成计算结果,需要用list()
函数获得所有结果并返回list。
最后作者介绍了一个使用埃式算法实现构建素数列表的一个例子
def _odd_iter(): n=3 while True: n+=2 yield n def _not_divisable(n): return lambda x:x%n>0#关于这一行代码,返回的是一个函数对象, def prime(): yield 2 it=_odd_iter() while True: n=next(it) yield n it=filter(_not_divisable(n),it)#这里的_not_divistable(n)实际是lambda x:x%n>0,虽然filter会把序列中的元素依次的传递给前面的函数,但是这个由lambda语句组成的函数对象只在filter执行的第一次时候被创建,然后后面的序列中的元素传给了x,即n并不会变 #看到这里为什么不把_not_divisable(n) 直接换为lambda x:x%n>0呢,因为这样就固定不了n的值了 for i in prime(): if i<1000: print(i) else: break #输出 会输出1000内的素数
排序sorted()
参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318230588782cac105d0d8a40c6b450a232748dc854000
可以对字符串和数字排序
sorted(iterable, /, *, key=None, reverse=False) Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order. key关键字指定一个函数,可以实现自定义的排序,详细过程是通过让每个元素都经过该函数的处理,形成一个新的副本,对这个副本进行排序,然后返回这个副本的排序结果中每个元素的原来值。
key=abs#按绝对值大小排序
key=str.lower#忽略大小写
sorted()
也是一个高阶函数。用sorted()
排序的关键在于实现一个映射函数。
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] def by_name(t): return t[0][0].lower()#注意是这样写的 def by_score(t): return t[0][1] L2 = sorted(L, key=by_name)#按名字排序 print(L2) #输出 [('Adam', 92), ('Bob', 75), ('Bart', 66), ('Lisa', 88)]
偏函数
参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143184474383175eeea92a8b0439fab7b392a8a32f8fa000
能不能让自定义的函数使用这个特性呢?想着是应该可以的吧
偏函数的作用就是把函数的一些参数(这个函数的返回值是一个函数,可以理解为用它来选择函数)给固定起来,或者说是可以在以后使用的时候传递其他值,而且使用非常方便
#使用int做N进制转换 >>> int('12345', base=8) 5349 #用下面这个例子引入偏函数 #我们要是自定义一个可以让int()中的base变成可以接受我们传入的进制的话是要这样 def int2(x, base_mark=2):***********************************************这里可以是base,也可以是basee return int(x, base_mark) >>> int2('1000000') 64 #使用python中提供的偏函数的话就可以将代码简化为这样 >>> import functools >>> int2 = functools.partial(int, base=2)#只需要一行代码***********************************************这里必须是base,不可以是basee
>>> int2('1000000') 64
也可以在调用时传入其他值
注意,构建偏函数时固定的参数如果是关键字参数,必须要使用原来的关键字,比如上面的base在定义的时候,即关键字要符合原来的函数
>>> int2('1000000', base=10) 1000000
当函数的参数个数太多,需要简化时,使用 functools.partial 可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。