18.python高阶函数

什么是高阶函数:一个函数可以作为参数传给另外一个函数(一个函数可以用来接收另一个函数作为参数),或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。函数的形参位置必须接受一个函数对象。

代码理解高阶函数的含义:

 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))

猜你喜欢

转载自www.cnblogs.com/bonheur/p/12374412.html