day17(匿名函数)

发布时间 2023-12-19 17:44:47作者: 王苗鲁

day17

1.函数式介绍

相比面向过程编程,函数式更加注重的是执行结果而非执行过程。代表语言有:Haskell、Erlang。而python并不是一门函数式编程语言,但是仍为我们提供了很多函数式编程好的特性,如lambda,map,reduce,filter。

2.匿名函数lambda

# 1.def用于定义有名函数
# func=函数内存地址
def func(x, y):
    return x + y


print(func)

# 2.lambda 用于定义匿名函数
print(lambda x, y: x + y)

# 3.调用匿名函数
# 方式一:
res = (lambda x, y: x + y)(1, 2)
print(res)

# 方式二:
func = lambda x, y: x + y
res = func(1, 2)
print(res)

# 4.匿名函数用于临时调用一次的场景:更多的是将匿名函数与其他函数配合使用
lambda x, y: x + y

总结:
# 1.匿名的目的就是要没有名字,给匿名函数赋给一个名字是没有意义的
# 2.匿名函数的参数规则、作用域关系与有名函数是一样的
# 3.匿名函数的函数体通常应该是、一个表达式,该表达式必须要有一个返回值
def func(x,y,z):
    return x+y+z

lambda x,y,z:x+y+z

3.lambda匿名函数应用之man与min

"""
max与min接收2个参数: 
	第一个参数是可迭代对象. 
	第二个参数是函数. 必须指定关键字形式: key=匿名函数
		不指定参数: 使用默认方式迭代比较.( 如果迭代的对象是字典, 那么默认迭代方式的是字典的key, 由key作为本次函数的比较依据。)
		指定参数: max与min会把迭代完毕以后的结果作为参数传给函数, 如果迭代的对象是字典,那么就会把字典迭代之后的结果。也就是字典的key当做参数。传给lambda函数赋值给定义的参数。然后以返回值作为比较依据	
"""
# 需求: 获取最大薪资或者最小薪资的那个人
salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}

# 函数max会迭代字典salaries, 迭代字典默认取出的key会当作参数传给指定的匿名函数.
# 比较依据: 将函数的返回值 salaries[k] 返回, 作为比较依据
# 返回结果: 将比较完毕以后的的参数k当作返回值
res = max(salaries, key=lambda k: salaries[k])
print(res)  # lili

res = min(salaries, key=lambda k: salaries[k])
print(res)  # jack

4.lambda匿名函数应用之sorted

'''
注意: 只能用于同种类型的数据排序, 除了整型和字符串类型. 如果是字符串排序, 是以每个字符之间对应的ASCII码进行比较. 如果是列表与列表之间的排序, 是以每个元素作为比较.

sorted接收3个参数: 
	第一个参数是可迭代对象.
	第二个参数是函数. 必须指定关键字形式: key=匿名函数. 
	第三个参数是排序顺序(默认从小到大reverse=False). 指定从大到小: reverse=True

运行原理:
	sorted函数会迭代可迭代对象中的每个元素, 把迭代后得到的值依次传给匿名函数, 如果是字典,那么迭代以后传给字典的就是key。最终,以匿名函数的返回值作为比较依据.排序完毕以后会返回默认迭代可迭代对象的方式。比如: 字典默认迭代的就是key。那么他就会以key作为你的返回值,虽然你比较的依据是字典的value。它的key是基于你value的排序结果排序的key。
'''
salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}
# 默认是按照字典的key进行排序的.
res = sorted(salaries)
print(res)  # ['jack', 'lili', 'siry', 'tom'] -- > 字符串比较按照ASCII码比较: 'j'(106) < 'l'(108) < 's'(115) < 't'(116)

# 需求: 按照薪资从小到大排序(默认升序 reverse=False)
res = sorted(salaries, key=lambda k: salaries[k])
# res = sorted(salaries, key=lambda k: salaries[k], reverse=False)
print(res)  # ['jack', 'siry', 'tom', 'lili']

# 需求: 按照薪资从大到小排序(reverse=True)
res = sorted(salaries, key=lambda k: salaries[k], reverse=True)
print(res)  # ['jack', 'siry', 'tom', 'lili']

5.lambda匿名函数应用之map映射

'''
map接收2个参数: 
	第一个参数是函数
	第二个参数是可迭代对象

运行原理:
	map函数会迭代你指定的可迭代对象中的每个元素, 把迭代得到的值当做参数传给匿名函数, 以返回值的处理结果当做返回值返回.(注意: map得到的结果是迭代器对象)
'''
# 需求: 将array的每个元素做平方处理
array = [1, 2, 3, 4, 5]
res = map(lambda item: item ** 2, array)
print(res)  # map得到的结果是迭代器对象. 返回结果: <map object at 0x00000176D87AFDF0>
print(list(res))  # [1, 4, 9, 16, 25]

# map的替代方案: 使用生成器表达式
res = (item ** 2 for item in array)
print(res)  # <generator object <genexpr> at 0x0000022EA48343C0>
print(list(res))  # [1, 4, 9, 16, 25]

6.lambda匿名函数应用之reduce合并

"""	
使用方法: 
    reduce在python2中是内置函数, 在python3中被集成到模块functools中, 需要导入使用

reduce接收三个参数:
	第一个参数是函数
	第二个参数是可迭代对象
	第三个参数是初始值

运行原理:
    没有指定初始值: reduce函数会迭代一次你指定的可迭代对象, 得到的值作为初始值, 作为第一个参数传给x, 然后继续迭代你指定的可迭代对象, 得到的第二个值传给y. x只在初始阶段被赋值一次, 并保留x的状态, 将每次y的值与x进行操作, 直至结束.
    有指定初始值: reduce函数会将指定的值作为初始值, 作为第一个参数传给x, 继续迭代你指定的可迭代对象, 得到的第二个值传给y. x只在初始阶段被赋值一次, 并保留x的状态, 将每次y的值与x进行操作, 直至结束.
"""
# 需求: 对array进行合并求和运算
from functools import reduce
array = [1, 4, 9, 16, 25]
res = reduce(lambda x, y: x + y, array, 0)
print(res)  # 55

# reduce的替代方案: sum
print(sum(array))  # 55

# reduce的替代方案: 使用生成器表达式 + sum
salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}
res = sum(value for value in salaries.values())
print(res)  # 22000

# 验证(重点理解): 保留x的状态, 将每次y的值与x进行操作, 直至结束
li = [1, '2', '3', '4']
res = reduce(lambda x, y: x + y if isinstance(y, int) else x + int(y), li)
print(res)  # 10

# 注意: x在初始阶段只被赋值一次, 并保留x的状态, 将每次y的值与x进行操作, 直至结束.
# (((10 - 1) - 2) - 3) = 4
res = reduce(lambda x, y: x - y, [1, 2, 3], 10)
print(res)

# ((1 - 2) - 3) = -4 
res = reduce(lambda x, y: x - y, [1, 2, 3])
print(res)

7.lambda匿名函数应用之filter过滤

'''
filter接收2个参数:
	第一个参数是函数
	第二个参数是可迭代对象
	
运行原理
	filter函数会依次迭代你指定的可迭代对象, 得到的值当实参依次传给匿名函数, 如果匿名函数的返回值为真, 则过滤出该元素. filter返回值是默认遍历完毕以后的对象。如果你是一个字典,默认遍历的是key。那么就算你过滤了以后,你返回的对象也是以key为主, 这个时候你使用list转换。list中元素就是刚刚遍历的字典的key。(注意: filter返回的结果是迭代器)
'''
# 需求: 对array进行过滤取出大于3小于16的数
array = [1, 4, 9, 16, 25]
res = filter(lambda item: 16 > item > 3 , array)
print(res)  # <filter object at 0x000001A219BEFDF0>

print(list(res))  # [4, 9]

# filter的替代方案: 使用生成器表达式
res = ()