python 高阶函数
一、python 高阶函数
1、变量可以指向函数
如py内置函数求绝对值的abs()
>>> abs(-10)
10
直接写abs
>>> abs
<built-in function abs>
返回的是函数,课件abs(-10)是函数调用,abs是函数本身
2、将函数也可以赋值变量,如
>>> f=abs
>>> f(-10)
10
>>> f
<built-in function abs>
3、函数名也是变量
函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数!
如果将abs指向对象
>>> abs=10
>>> abs
10
>>> abs(-10)
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
abs(-10)
TypeError: 'int' object is not callable
可以看出把abs指向10后,就无法通过abs(-10)调用该函数了!因为abs这个变量已经不指向求绝对值函数而是指向一个整数10!
二、传入函数
1、既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数
如:
def add(x,y,abs):
return abs(x)+abs(y)
c =add(-1,-1,abs)
print(c)
>>>2
当我们调用add(-5, 6, abs)时,参数x,y和f分别接收-5,6和abs
三、map/reduce
Python内建了map()和reduce()函数。
1、map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
如:要计算list每个元素的平方
一般我们通过遍历即可
lst =[1,2,3]
lst_2 =[]
for i in lst:
lst_2.append(i*i)
print(lst_2)
>>>[1, 4, 9]
如果用map实现的话
map(f,lst)
现在只需要写一个f函数求每位数的平方即可
def f(x):
return x*x
map(f,lst)
r=list(map(f,lst))
print(r)
>>>[1, 4, 9]
所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,
如将列表元素取绝对值
lst =[-1,-2,3]
r=list(map(abs,lst))
print(r)
>>>[1, 2, 3]
将其转换为字符串
rr =list(map(str, lst))
print(rr)
>>>['-1', '-2', '3']
2、reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
如对列表求和:
from functools import reduce
lst =[-1,-2,3]
def add(x,y):
return x+y
r =reduce (add,lst)
print(r)
>>>0
执行过程如下
--add(-1,-2) return -3
--add(-3,3) return 0
四、和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
如:回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()滤掉非回数:
a、用常规方法
import math
def not_divisible(nums):
lst =[x for x in range(10,nums)]
lst_ss=[]
for n in lst:
lst=list(str(n))
if len(lst)%2==0:
#[1,2]
i,j=int(len(lst)/2)-1,int(len(lst)/2)
#print("$$$$$$$$$$$$$$$$$$$$$$$")
#print("NNN"+str(n))
flg=True
if j<len(lst) and j>=0:
while flg:
#print("lst[i]==="+str(lst[i]))
#print("lst[j]==="+str(lst[j]))
#print("^^^^^^^^^^^^^^^")
if lst[i]==lst[j]:
if j==len(lst)-1:
#print("lst is")
lst_ss.append(n)
flg=False
else:
i-=1
j+=1
#print("**************")
#print(i)
#print(j)
else:
#print("lst not")
flg=False
if (len(lst)%2)!=0:
#[1,2,1]
i,j=int(math.ceil(len(lst)/2))-1,int(len(lst)/2)
#print("$$$$$$$$$$$$$$$$$$$$$$$")
#print("NNN"+str(n))
flg=True
if j<len(lst) and j>=0:
while flg:
#print("lst[i]==="+str(lst[i]))
#print("lst[j]==="+str(lst[j]))
#print("^^^^^^^^^^^^^^^")
if lst[i]==lst[j]:
if j==len(lst)-1:
#print("lst is")
lst_ss.append(n)
flg=False
else:
i-=1
j+=1
#print("**************")
#print(i)
#print(j)
else:
#print("lst not")
flg=False
print(lst_ss)
not_divisible(1000)
b、用list切片
import math
def not_divisible(nums):
lst =[x for x in range(10,nums)]
lst_ss=[]
for n in lst:
lst=list(str(n))
if lst==lst[::-1]:
lst_ss.append(n)
print(lst_ss)
not_divisible(1000)
c、用filter
def is_palindrome(n):
return str(n)[::-1]==str(n)
out=filter(is_palindrome,list(range(1,1000)))
print(list(out))
五、sorted
1、对list进行排序
如:sorted([36, 5, -12, 9, -21])
>>>[-21, -12, 5, 9, 36]
sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序
如:sorted([36, 5, -12, 9, -21],key=abs)
>>>[5, 9, -12, -21, 36]
key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。对比原始的list和经过key=abs处理过的list:
list = [36, 5, -12, 9, -21]
keys = [36, 5, 12, 9, 21]
然后sorted()函数按照keys进行排序,并按照对应关系返回list相应的元素:
keys排序结果 => [5, 9, 12, 21, 36]
最终结果 => [5, 9, -12, -21, 36]