什么是高阶函数:一个函数可以作为参数传给另外一个函数(一个函数可以用来接收另一个函数作为参数),或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。函数的形参位置必须接受一个函数对象。
代码理解高阶函数的含义:
1 '''函数当做参数被传递到另个函数是什么样的。把abs()函数赋值给了f变量,接下来就可以像使用abs()函数本身那样使用f变量了,区别只是换了个名字而已''' 2 3 f = abs # 将求绝对值的abs函数赋值给f变量 4 f(-123) # f变量等同于abs函数的功能和性质,区别只是换了个别名 5 print(f(-123)) # 输出结果 123 6 print(type(f)) # <builtin_function_or_method> 查看下这个f变量的类型,显示为内置函数,因为它的真身就是内置abs()函数 7
8 '''这说明变量可以指向函数,既然变量可以指向函数,而我们知道函数的参数可以接收变量。也就是说一个函数可以接收另一个函数作为参数,一起来看看下面这个例子''' 9 def add_(a, b, f_): 10 return f_(a) + f_(b) # 在本例中等同于 abs(a) + abs(b) 11 12 result = add_(-10, -20, abs) # 这里把python内置函数abs作为参数传递给add_ 13 print(result) # 30
代码演示高阶函数两种场景:
1 # 高阶函数之 ---》参数为函数 2 def bar(): 3 print("in the bar..") 4 def foo(func): 5 func() 6 print("in the foo..") 7 8 foo(bar) 9 10 11 # 高阶函数之 ---》返回值为函数 12 def bar(): 13 print("in the bar..") 14 def foo(func): 15 print("in the foo..") 16 return bar 17 res=foo(bar) 18 res() 19 20 '''以上两个示例中,函数foo()为高阶函数。示例一中函数bar作为foo的参数传入;示例二中函数bar作为foo的返回值。
注意:函数名(例如bar 、foo)-->其为该函数的内存地址;函数名+括号(例如 bar()、foo() )-->调用该函数'''
python里的高阶函数有 filter、map、reduce、sorted、匿名函数lambda,递归函数等。
分类学习:
1).map(fn,lsd1,[lsd2]):
参数一:fn --> 函数对象
参数二:lsd1 --> 序列对象(字符串、列表、range...)
功能:
将fn函数作用于lsd1中的每一个元素上,
将每次执行的结果存入到一个map对象中返回;
【注意】得到的这个map对象是一个迭代器对象,属于惰性序列的范畴
需求:lt = ['1','2','3','4','5'] --> [1,2,3,4,5]
#代码实现一:使用老技术来实现
lt = ['1','2','3','4','5','6']
lt1 = []
for i in lt:
num = int(i)
lt1.append(num)
#由于列表属于非惰性序列范畴,即可以直接打印看效果
print(lt1) # [1, 2, 3, 4, 5, 6]
#代码实现二:使用新技术来实现
#思路步骤一:定义一个函数,功能:将str数据 --> int数据
import collections
lt = ['1','2','3','4','5','6']
def chr2Int(chr):
#① return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,
'9':9}.[chr]
#② return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,
'9':9}.get(chr)
#③ return int(chr) 比上面两个字典通过键匹配值简便很多,int强转
mo = map(chr2Int,lt) #这里的chr2Int后面不能加(),也不能传参*****
print(map,type(mo)) # <class 'map'> <class 'map'>
print(isinstance(mo,collections.Iterator)) # True
上面代码是验证以下,是迭代器对象才能用next,返回 True,所以可以
print(next(mo)) # 1
将map对象(惰性的)转换为list对象(非惰性的)
print(list(mo)) #[2, 3, 4, 5, 6]
************************************************
#代码实现三:终极操作
print(list(map(chr2Int,lt))) #[1, 2, 3, 4, 5, 6]
print(list(map(int,lt)) #[1, 2, 3, 4, 5, 6]
map(int,lt):执行过程如下:
1).lt --> 取出第一个元素:'1'当做实际参数传递给int函数的形参位置 --> int('1')
将转换以后的结果:1保留到map对象的第一个元素位置
2).lt --> 取出第二个元素:'2'当做实际参数传递给int函数的形参位置 --> int('2')
将转换以后的结果:2保留到map对象的第二个元素位置
以此类推...
直到map函数执行完了,整个map对象才真正成型了...
需求1:lt = [1,2,3,4,5] --> 得到:['1','2','3','4','5']
lt = [1,2,3,4,5]
#自定义函数:从int --》 str
def int2Str(i):
return str(i)
print(list(map(int2Str,lt))) #['1', '2', '3', '4', '5']
print(list(map(str,lt))) #['1', '2', '3', '4', '5']
print(list(map(lambda x: str(x),lt))) #['1', '2', '3', '4', '5']
需求2:lt = [1,2,3,4,5] --> 得到:[1,4,9,16,25]
lt = [1,2,3,4,5]
#自定义函数:目标实现开方操作
def kaifang(num):
return num ** 2
print(list(map(kaifang,lt))) # [1, 4, 9, 16, 25]
#或者map结合匿名函数使用,用的比较多
print(list(map(lambda x: x ** 2,lt))) # [1, 4, 9, 16, 25]
2).reduce(fn,lsd):
参数一:fn --> 函数对象
参数二:lsd --> 序列对象
功能:
先将lsd中的第一和第二个元素传入到fn中参与运算,
运算后得到结果,再和第三个元素传入到fn中参与运算,
以此类推...
【注意】:reduce函数属于functools模块中的函数,所以需要显示的先导入functools模块再使用from functools import reduce
tp = (1,2,3,4)
自定义函数 --> add 作用:对列表中的元素进行求和操作 def add(x,y)
使用reduce函数执行过程如下:
第一次:add(1,2)
第二次:add(add(1,2),3)
第三次:add(add(add(1,2),3),4)
#需求:得到元祖中元素的和值
tp = (1,2,3,4)
#代码实现一:递归的思想来实现
def mySum(num):
if num == 1:
return 1
return num + mySum(num - 1)
print(mySum(4))
#代码实现二:新技术(reduce)
from functools import reduce
def add(x,y):
return x + y
res = reduce(add,tp)
print(res,type(res)) #10 <class 'int'>
print(reduce(lambda x,y: x + y,tp))
print(sum(tp)) #直接使用内置函数sum()了
#需求:lt = [1,2,3,4] 得到其中元素的乘积
lt = [1,2,3,4]
print(reduce(lambda x,y: x * y,lt))
需求:从键盘读入一个整数字符串数据,例如:'12345'
需要将其转换为12345;注意:不能直接使用int()来实现
思路:使用map和reduce配合来实现
步骤一:'12345' --》拆分为散装数据:1 2 3 4 5 可以使用map来实现
步骤二:将map对象中的数据 1 2 3 4 5 组合成为 --> 12345 可以使用reduce来实现
from functools import reduce
str1 = '12345'
def chr2Int(str):
return int(str)
def zuhe(x,y):
return x * 10 + y
mo = map(chr2Int,str1)
num = reduce(zuhe,mo)
print(num,type(num)) #12345 <class 'int'>
#终极版:
print(reduce(lambda x,y: x * 10 + y,map(int,str1))) #12345
3).filter(fn,lsd):
filter函数:过滤数据的,最终返回一个惰性序列对象(filter对象,迭代器对象)
解释:filter的意思:在计算机领域中我们都称为过滤器
格式:filter(fn,lsd):
参数和map、reduce一样理解
功能:
将lsd中的每一个元素都给到fn函数
如果fn函数的返回值为True,那么就保留这个元素到filter对象中
如果fn函数的返回值为False,那么就舍弃这个元素,不会保留到filter对象中
最终filter函数执行完毕了,返回给程序一个filter对象(迭代器对象)
#需求:lt = [1,2,3,4,5,6,7,8] --> 得到:[2,4,6,8]
lt = [1,2,3,4,5,6,7,8]
#代码实现一:老技术
lt1 = []
for i in lt:
if i % 2 == 0:
lt1.append(i)
print(lt1)
#代码实现二:新技术(filter)
def func(o):
if o % 2 == 0:
return True
return False
fo =filter(func,lt)
print(fo,type(fo)) #<filter object at 0x0000000001E8F710> <class 'filter'>
print(list(filter(func,lt))) #[2, 4, 6, 8]
print(isinstance(fo,collections.Iterator)) #Ture
print(isinstance(fo,collections.Iterable)) #Ture
print(next(fo)) #2
print(next(fo)) #4
print(list(fo)) #[6, 8]
# 终极版:
print(list(filter(lambda x:x % 2 == 0,lt))) #[2, 4, 6, 8]
需求1:
lt = [345,0,'abcde',1.2,0,3.14,0.0,'haha','hehe',True,False,[]
,(),{},{1,2,3},[10,20,30],{'name':'zs','age':30},None]
得到如下效果:
lt = [345,'abcde',1.2,3.14,'haha','hehe',True,{1,2,3},[10,20,30],{'
name':'zs','age':30}]
lt = [345,0,'abcde',1.2,0,3.14,0.0,'haha','hehe',True,False,[]
,(),{},{1,2,3},[10,20,30],{'name':'zs','age':30},None]
print(list(filter(lambda x: bool(x),lt)))
#或者
print(list(filter(bool,lt)))
需求2:lt1 = ['aaaaaaaa','bbbbb','cccccc','ddd']
得到如下效果:['aaaaaaaa','cccccc']
lt1 = ['aaaaaaaa','bbbbb','cccccc','ddd']
print(list(filter(lambda x: len(x) > 5,lt1)))
归纳总结:高阶函数以及匿名函数之间的配合使用:
模板一:lambda和filter的配合使用
#需求:lt = [1,2,3,4,5,6,7,8,9] --> 得到[3,6,9]
lt = [1,2,3,4,5,6,7,8,9]
print(list(filter(lambda x: x % 3 == 0,lt)))
模板二:lambda 和map的配合使用
#需求:演示开平方操作 --> 容器对象:range
mo = map(lambda x: x ** 2,range(5))
print(list(mo))
模板三:在模板二的基础上进行功能扩展:range(10)
过滤以后保留的数据范围大小为:(5,50)之间
mo = map(lambda x: x ** 2,range(10))
fo = filter(lambda x: x > 5 and x < 50,mo)
print(list(fo))
模板四:lambda 和reduce配合使用
#求和值
import functools
lt = [1,2,3,4,5]
my_sum = functools.reduce(lambda x,y: x + y,lt)
print(my_sum)
模板五:求两个列表对象中元素的和,返回新列表
lt1 = [1,2,3,4]
lt2 = [5,6]
结果:lt3 = [6,8,10,12]
lt1 = [1,2,3,4]
lt2 = [5,6]
mo = map(lambda x,y: x + y,lt1,lt2)
print(list(mo))
模板六:求字符串中每个单词的长度
content = "welcome to shanghai"
结果:[7,2,8]
content = "welcome to shanghai"
#使用切割的思想:切完之后得到一个列表对象,内部元素为["welcome","to","shanghai"]
words_list = content.split()
mo = map(len,words_list)
print(list(mo))