Python 提供了非常多的库和内置函数。有不同的方法可以执行相同的任务,而在 Python 中,有个万能之王函数:lambda 函数,它以不同的方式在任何地方使用。
一、Lambda 函数简介
在 Python 中,函数可以接受一个或多个位置参数或关键字参数、可变参数列表、可变关键字参数列表等。它们可以传递给高阶函数并作为输出返回。常规函数可以有多个表达式和多个语句。
Python lambda 函数只是一个匿名函数。它也可以称为无名函数。它直接接受参数的数量以及使用该参数执行的条件或操作,该参数以冒号分隔,并返回最终结果。
普通的 Python 函数由def关键字定义。Python 中的 Lambda 函数通常由lambda关键字、任意数量的参数和一个表达式组成。
Lambda 函数主要用作单行函数。它们经常在高阶函数中使用,例如map()和filter()。这是因为匿名函数作为参数传递给高阶函数。
lambda argument_list:expersion
argument_list是参数列表,它的结构与Python中函数(function)的参数列表是一样的
expression是一个关于参数的表达式,表达式中出现的参数需要在argument_list中有定义,并且表达式只能是单行的。
其中它可以接受任意数量的参数,但是只允许包含一个表达式,而该表达式的运算结果就是函数的返回值,我们可以简单地来写一个例子
(lambda x:x**2)(3)
二、为什么要使用Lambda函数?
一般情况下,我们不使用Lambda函数,而是将其与高阶函数一起使用。高阶函数是一种需要多个函数来完成任务的函数,或者当一个函数返回任何另一个函数时,可以选择使用Lambda函数。
什么是高阶函数
高阶函数的概念在 Python 中很流行,就像在其他语言中一样。它们是接受其他函数作为参数并返回函数作为输出的函数。
在 Python 中,高阶函数有两个参数:一个函数和一个可迭代对象。函数参数应用于可迭代对象中的每个项目。由于我们可以将函数作为参数传递给高阶函数,因此我们同样可以传入 lambda 函数。
三、Python高阶函数
在 Python 中,高阶函数有两个参数:一个函数和一个可迭代对象。函数参数应用于可迭代对象中的每个项目。由于我们可以将函数作为参数传递给高阶函数,因此我们同样可以传入 lambda 函数。
例如filter()、 map()和reduce()— 它是从 Python 中的 functools 模块导入的,因为它不是内置函数。默认情况下,高阶函数是接收其他函数作为参数的函数。
1、Map函数
map() 会根据提供的函数对指定序列做映射。
Map函数是一个接受两个参数的函数。第一个参数 function 以参数序列中的每一个元素调用 function 函数,第二个是任何可迭代的序列数据类型。返回包含每次 function 函数返回值的新列表。
map(function, iterable, ...)
Map函数将定义在迭代器对象中的某种类型的操作。假设我们要将数组元素进行平方运算,即将一个数组的每个元素的平方映射到另一个产生所需结果的数组。
# coding=utf-8# 10以内的平方
square_of_numbers = list(map(lambda x: x ** 2, range(10)))print(square_of_numbers)strings = ['Nigeria', 'Ghana', 'Niger', 'Kenya', 'Ethiopia', 'South Africa', 'Tanzania', 'Egypt', 'Morocco', 'Uganda']
# 获取字符串长度
length_of_strings = list(map(lambda x: len(x), strings))print(length_of_strings)
以不同的方式使用Map函数。假设有一个包含名称、地址等详细信息的字典列表,目标是生成一个包含所有名称或者地址的新列表。
# coding=utf-8students = [{"name": "John Doe","father name": "Robert Doe","Address": "123 Hall street"},{"name": "Rahul Garg","father name": "Kamal Garg","Address": "3-Upper-Street corner"},{"name": "Angela Steven","father name": "Jabob steven","Address": "Unknown"}
]
print(list(map(lambda student: student['name'], students)))
print(list(map(lambda student: student['Address'], students)))
2、Filter函数
Filter函数根据给定的特定条件过滤掉数据。即在函数中设定过滤条件,迭代元素,保留返回值为True 的元素。Map 函数对每个元素进行操作,而 filter 函数仅输出满足特定要求的元素。
filter(function or None, iterable) --> filter object
返回一个迭代器,为那些函数或项为真的可迭代项。如果函数为None,则返回为真的项。
假设有一个水果名称列表,任务是只输出那些名称中包含字符“g”的名称。
# coding=utf-8fruits = ['mango', 'apple', 'orange', 'cherry', 'grapes']
print(list(filter(lambda fruit: 'g' in fruit, fruits)))
假设有一个字符串列表,任务是只输出那些字符串长度大于6的
# coding=utf-8strings = ['Nigeria', 'Ghana', 'Niger', 'Kenya', 'Ethiopia', 'South Africa', 'Tanzania', 'Egypt', 'Morocco', 'Uganda']# 字符串长度大于6的
length_of_strings_above_six = list(filter(lambda x: len(x) > 6, strings))print(length_of_strings_above_six)
3、Reduce函数
这个函数比较特别,不是 Python 的内置函数,需要通过from functools import reduce 导入。Reduce 从序列数据结构返回单个输出值,它通过应用一个给定的函数来减少元素。
reduce(function, sequence[, initial]) -> value
将包含两个参数的函数(function)累计应用于序列(sequence)的项,从左到右,从而将序列reduce至单个值。
如果存在initial,则将其放在项目之前的序列,并作为默认值时序列是空的。
假设有一个整数列表,并求得所有元素相乘。且使用reduce函数而不是使用for循环来处理此问题。
# coding=utf-8from functools import reduce
nums = [2, 4, 6, 8, 10]
multiplication_of_nums = reduce(lambda x, y: x * y, nums)print(multiplication_of_nums)def mul_numbers(x, y):return x * yprint(reduce(mul_numbers, nums))
还可以使用 reduce 函数而不是for循环从列表中找到最大或最小的元素。
# coding=utf-8from functools import reduce
values = [13, 6, 12, 23, 15, 31, 16, 21]
min_value = reduce(lambda x, y: x if (x < y) else y, values)
max_value = reduce(lambda x, y: x if (x > y) else y, values)
print(min_value)
print(max_value)
四、高阶函数的替代方法
1、列表推导式
其实列表推导式只是一个for循环,用于添加新列表中的每一项,以从现有索引或一组元素创建一个新列表。之前使用map、filter和reduce完成的工作也可以使用列表推导式完成。然而,相比于使用Map和filter函数,很多人更喜欢使用列表推导式,也许是因为它更容易应用和记忆。
同样使用列表推导式将数组中每个元素进行平方运算,水果的例子也可以使用列表推导式来解决。
arr = [2,4,6,8]
arr = [i**2 for i in arr]
print(arr)
fruit_result = [fruit for fruit in fruits if 'g' in fruit]
print(fruit_result)
2、字典推导式
与列表推导式一样,使用字典推导式从现有的字典创建一个新字典。还可以从列表创建字典。
假设有一个整数列表,需要创建一个字典,其中键是列表中的每个元素,值是列表中的每个元素的平方。
# coding=utf-8nums = [2, 4, 6, 8, 10]
D1 = {item: item ** 2 for item in nums}
print(D1)
# 创建一个只包含奇数元素的字典
arr = [1, 2, 3, 4, 5, 6, 7, 8]
D2 = {item: item ** 2 for item in arr if item % 2 != 0}
print(D2)
五、简单应用:如何快速找到多个字典的公共键
方法一
dl = [d1, d2, d3] # d1, d2, d3为字典,目标找到所有字典的公共键
[k for k in dl[0] if all(map(lambda d: k in d, dl[1:]))]
dl = [{1:'life', 2: 'is'}, {1:'short', 3: 'i'}, {1: 'use', 4: 'python'}]
[k for k in dl[0] if all(map(lambda d: k in d, dl[1:]))]
# 1
# 列表表达式遍历dl中第一个字典中的键
[k for k in dl[0]]
# [1, 2]# lambda 匿名函数判断字典中的键,即k值是否在其余字典中
list(map(lambda d: 1 in d, dl[1:]))
# [True, True]
list(map(lambda d: 2 in d, dl[1:]))
#[False, False]# 列表表达式条件为上述结果([True, True])全为True,则输出对应的k值
#1
方法二
# 利用集合(set)的交集操作
from functools import reduce
# reduce(lambda a, b: a*b, range(1,11)) # 10!
reduce(lambda a, b: a & b, map(dict.keys, dl))
六、写在最后
目前已经学习了Lambda函数是什么,以及Lambda函数的一些使用方法,以及如何在高阶函数中使用lambda函数。
代码的可读性应优先于简洁性。尽管 Python lambda 可以显著减少编写的代码行数,但应谨慎使用,仅在必要时才使用。
Lambda 可以非常方便地使用 Python 三元表达式,但同样不要牺牲可读性。当使用高阶函数时,Lambda 函数真正发挥作用。
总之:
Python lambda 非常适合编写单行函数。
它们也用于 IIFE(立即调用的函数表达式)。
当有多个表达式时不应使用 Lambda,因为它会使代码不可读。