本教程将深入讲解如何使用Python的Lambda函数。您将理解它们在函数式编程中的作用,以及它们如何简化代码。此外,您还将了解Lambda函数的基本用例和高级用例。
Lambda函数本质上是小型匿名函数,适用于需要短时间内使用简单函数的场景。您可以在需要它们的地方直接创建这些函数。它们通常简洁且只有一行代码。Lambda函数使您的代码更加清晰,易于理解。
与传统函数使用Python关键字def
不同,您可以使用关键字lambda
来创建这种类型的函数。您将很快学习Lambda函数的语法。
前提条件
本教程适合初学者到中级Python程序员。然而,对于那些对Python Lambda函数或编程感兴趣但不在此范围内的好奇者来说,这个教程也足够简单,便于理解。
您需要:
- Python ≥ 版本 3.0.0
- 任何代码编辑器(推荐使用Pycharm)
Lambda 函数
想象一下,你正在解决一个复杂的数学问题(没有计算器),需要快速对一串数字进行求和。你可以选择痛苦地将整个方程写下来,但这可能会花费很多时间,对于简单的求和来说显得过于繁琐。
与其浪费宝贵的时间,你可以拿一张便利贴来进行求和。在 Python 中,lambda 函数扮演着类似的角色。它是一种可以用来完成简单任务的函数,而无需创建一个“正常”的函数。然而,就像便利贴一样,Python 程序员在需要时使用 lambda 函数,之后会将其丢弃。
如何创建 Lambda 函数
你可以通过输入 Python 关键字 lambda
来创建一个 lambda 函数,后面跟上函数的参数(如果有多个参数,用逗号分隔),然后添加一个冒号和函数执行的操作(一个单一的操作)。
语法:
lambda (arguments): (expression)
以下是上述语法的详细说明:
lambda
是 Python 关键字,表示您正在创建一个 lambda 函数arguments
是函数接受的输入,可以有任意数量(与常规函数相同)expression
是函数执行的操作(通常是单一操作)并返回结果
需要注意的是,lambda 函数返回的是表达式的值。Python 程序员不需要显式地编写 return
语句。
示例1 lambda 函数:
# 接受一个整数 ‘x’ 并返回它的平方
square = lambda x: x * x
示例2 传统函数:
# 接受一个整数 'x' 并返回它的平方
def square(x):
return x * x
上面的 示例2 中的函数相比于 示例1 中的函数多了一行。尽管语法不同,但这两个函数的作用相同。
Lambda 函数与常规函数
这两种函数类型具有某些特性,使它们彼此不同。让我们并排比较一下 lambda 函数和常规函数:
特性 | Lambda 函数 | 常规函数 |
---|---|---|
定义 | 使用 lambda 的单行 |
def function_name(): 和一个代码块 |
命名 | 匿名 | 有指定名称 |
大小 | 单行,简洁 | 对于复杂逻辑可以有多行 |
作用域 | 通常在其他函数内使用 |
通常独立存
返回值
返回表达式的结果
使用Python关键字return
来指定输出
Python如何看待Lambda函数和常规函数?
你可能会想知道Python解释器是如何在底层区分Lambda函数和传统函数的。你很快就会找到答案。
Python 有一个 dis 模块,它将解释器通常处理的编译指令(Python 字节码)转换为人类可读的形式。该模块允许 Python 程序员窥探 Python 代码是如何被转换为计算机所理解的。这一特性帮助程序员调试代码,以及其他功能。
现在,你将使用 dis
模块对上面示例中的函数 示例1 和 示例2 进行探索,看看其背后的运作。请在你的 Python 控制台上运行这些函数:
>>> import dis
>>> square = lambda x: x * x
>>> type(square)
<class 'function'>
>>> dis.dis(square)
1 0 LOAD_FAST 0 (x)
2 LOAD_FAST 0 (x)
4 BINARY_MULTIPLY
6 RETURN_VALUE
>>> square
<function <lambda> at 0x103660670>
如上所示,使用来自 dis
模块的 dis()
方法,可以以可读的格式展示 Python 字节码,这将帮助您检查解释器是如何执行程序的。
让我们看看普通函数会发生什么:
>>> import dis
>>> def square(x):
... return x *
>>> type(square)
<class 'function'>
>>> dis.dis(square)
2 0 LOAD_FAST 0 (x)
2 LOAD_FAST 0 (x)
4 BINARY_MULTIPLY
6 RETURN_VALUE
>>> square
<function square at 0x1063a6670>
使用 dis()
方法揭示 Python 的解释显示,这两个函数的解释方式是相同的。然而,它们的命名却不同。使用 def
创建的函数名称为 square
,而使用 lambda
定义的另一个函数名称为 <lambda>
。这种命名约定证明了 lambda 对这两个函数的看法是不同的,尽管它们的字节码解释是相同的。
使用 Lambda 函数
现在你知道了什么是 lambda 函数及其基本语法,你将学习如何在 Python 程序中使用它。
简单的 Lambda 函数
您可以使用 lambda 表达式进行简单的操作,例如加一对数字、对一个整数进行平方或将字符串转换为大写。
请考虑以下示例:
>>> # 示例 1:用于加两个数字的 Lambda 函数
>>> sum = lambda x, y: x + y
>>> print(sum(3, 5))
8
>>> # 示例 2:用于平方一个数字的 Lambda 函数
>>> square = lambda x: x * x
>>> print(square(4))
16
>>> # 示例 3:将字符串转换为大写的 Lambda 函数
>>> to_upper = lambda s: s.upper()
>>> print(to_upper("hello"))
HELLO
你可以看到上面的lambda表达式是多么简洁。这些函数在你需要对数字列表进行排序或转换列表的数据元素时非常有用。
多参数的Lambda表达式
与传统函数一样,lambda表达式也能够接受多个参数。这些参数通常用逗号分隔。多参数的lambda函数在处理需要混合来自多个源的数据时通常是有利的。当你在某个操作中配对数据时,这些函数也会很有帮助。
假设你有一组坐标(x,y)需要进行排序。你可以通过每个坐标的第一个数字来排序它们。但是如果你想根据每对坐标的和来排序呢?这时lambda表达式就派上用场了。请看下面的详细说明:
>>> coordinates = [(3, 2), (-1, 5), (0, 0)]
>>> sorted_coordinates = sorted(coordinates, key=lambda point: point[0] + point[1])
>>> print(sorted_coordinates)
这段代码首先定义了一个坐标列表 `coordinates`,其中包含三个点的坐标。接着,使用 `sorted` 函数对这些坐标进行排序,排序的依据是每个点的横坐标与纵坐标之和。最后,打印出排序后的坐标列表 `sorted_coordinates`。
[(0, 0), (-1, 5), (3, 2)]
在上面的代码块中:
-
- 我们使用Python的内置函数
sorted()
来对coordinates
列表进行排序 sorted()
接受两个参数:要排序的项目和key
参数(可选)
- 我们使用Python的内置函数
- 参数
key
指定了一个 lambda 函数,该函数为coordinates
中的每个元素计算自定义排序键 - 该 lambda 函数接受一个参数
point
,它表示coordinates
中的每个 元组 point[0]
和point[1]
分别表示 x 坐标和 y 坐标sorted_coordinates
包含了来自coordinates
的元组,按照它们的 x 坐标和 y 坐标之和进行排序
使用 Lambda 与内置函数
在学习如何将 lambda 与 Python 内置函数结合使用之前,您必须了解 高阶函数。在常规编程中,函数通常对数字、文本或其他简单数据执行操作。然而,高阶函数更进一步。这种类型的函数接受其他函数作为参数或返回一个函数作为结果。
高阶函数是函数式编程中的一个基本概念。此外,函数式编程强调使用函数来转换数据。
在Python中,有三个常用的高阶函数:map()
、filter()
和reduce
。你将学习如何将这些函数与lambda表达式一起使用。
如何将Lambda与Map()一起使用
map(function, iterable, *iterables)
Python 内置的 map()
函数接受两个参数——function
和 iterable
。它将给定函数的操作应用于可迭代对象中的每个项目(例如 列表、字符串 或元组),并返回一个包含结果的新迭代器。该函数可以接受尽可能多的可迭代参数,并将指定的函数应用于它们。
示例
>>> # 使用 map() 和 lambda 函数将列表中每个元素翻倍
>>> numbers = [1, 2, 3, 4, 5]
>>> doubled_numbers = list(map(lambda x: x * 2, numbers))
>>> print(doubled_numbers)
[2, 4, 6, 8, 10]
在这个例子中:
- 函数
lambda x: x * 2
被应用于numbers
中的每个整数 - 内置的
list()
被用来将map()
返回的迭代器转换为一个扩展列表,以便你的 Python 控制台可以显示
如何使用 Lambdas 与 Filter()
filter(function, iterable)
filter()
接受两个参数——function
和 iterable
。这个 Python 内置函数的工作方式与其名称所暗示的一样。它从可迭代对象的元素中创建一个迭代器,只有当指定的函数返回 true 时,这些元素才会被包含在内。实际上,它过滤掉那些在函数参数中返回 false 的可迭代对象的元素。因此,只有那些在函数中返回 true 的可迭代对象的元素才能进入新的迭代器。
示例
>>> # 使用 filter() 和 lambda 函数从列表中过滤出偶数
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
>>> print(even_numbers)
[2, 4, 6]
上面的例子表明:
lambda x: x % 2 == 0
被应用于每个numbers
的元素- 只有对该函数返回 true 的元素会出现在结果列表中
- 内置的
list()
将map()
返回的迭代器转换为一个扩展的列表,以便你的 Python 控制台可以显示
如何使用 Lambdas 与 Reduce()
functools.reduce(function, iterable, [initializer])
reduce()
函数会将一个函数重复应用于列表中的项,从而将其“归约”为单个项。可以将这个函数想象成一个机器,它收集多个原料并根据配方(函数)将其组合,直到菜肴准备好。
reduce()
函数在 functools 模块 中可用。它接受三个参数:要应用的函数、一个可迭代对象和一个可选的初始值。该函数对可迭代对象的项进行累积操作,从左到右,直到获得一个单一的值。
示例
>>> # 使用 reduce() 和 lambda 函数计算列表中所有元素的总和
>>> from functools import reduce
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> total_sum = reduce(lambda x, y: x + y, numbers, 0)
>>> print(total_sum)
21
在这个例子中:
-
- 由于
reduce()
可在functools
模块中使用,因此你需要从那里导入它
- 由于
-
lambda x, y: x + y
以累积的方式应用于numbers
的元素,从左到右,起始值为 0
-
- 该函数计算元素的成对和
Lambda 函数的高级用例
你已经学习了如何使用 lambda 函数进行简单的 Python 操作。现在,你将了解并探索一些 Python 程序员也会使用 lambda 的高级案例。
列表推导中的 Lambda 函数
列表推导式 允许 Python 程序员即时定义和创建列表。当您需要快速转换或对现有列表应用过滤时,将 lambda 引入列表推导式可以提供清晰和简洁的表达。
示例
考虑以下各种任务,其中在列表推导式中使用了 lambda 函数:
1. 使用 lambda 函数通过列表推导式将列表中的每个元素翻倍
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> doubled_numbers = [(lambda x: x * 2)(x) for x in numbers]
>>> print(doubled_numbers)
[2, 4, 6, 8, 10, 12]
在上述示例中:
- 对于
numbers
列表中的每个元素x
,定义并调用lambda x: x * 2
,使用当前的x
值 - 该 lambda 函数接受一个输入
x
并返回x * 2
- 倍增后的值被收集到
doubled_numbers
列表中
2. 使用带有 lambda 函数的列表推导从列表中过滤偶数
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> even_numbers = [x for x in numbers if (lambda x: x % 2 == 0)(x)]
>>> print(even_numbers)
[2, 4, 6]
在这个例子中:
- 该函数检查
x
的值是否为偶数,通过取模操作x % 2 == 0
- 如果结果为
True
,则表示x
是偶数,并被包含在even_numbers
列表中
3. 使用列表推导和 lambda 函数结合两个列表中的元素
>>> names = ["Alice", "Bob", "Charlie"]
>>> ages = [25, 39, 34]
>>> person_info = [(lambda name, age: (name, age) )(name, age) for name, age in zip(names, ages)]
>>> print(person_info)
[('Alice', 25), ('Bob', 39), ('Charlie', 34)]
在上述代码块中:
person_info
使用zip()
函数遍历names
和ages
列表中对应的元素zip()
用于将多个可迭代对象组合成一个包含元组的单一可迭代对象- 列表推导式生成一个元组列表,每个元组分别包含一个名字和对应的年龄
使用 Lambda 排序
Python 配备了一个内置的 sorted()
函数,允许程序员对可迭代对象进行排序。但使这个函数强大的原因在于它的 key
参数,这使得你可以自定义函数对可迭代对象的排序方式。你可以使用 lambda 函数来定义自定义的排序标准。
使用 lambda 进行自定义的能力允许灵活的即时排序,而无需显式创建一个单独的比较函数。
示例
请看下面的简单示例:
1. 使用 lambda 函数根据第二个元素对元组列表进行排序
points = [(1, 5), (3, 2), (2, 7)]
sorted_points = sorted(points, key=lambda x: x[1])
print(sorted_points)
[(3, 2), (1, 5), (2, 7)]
在上面的示例中:
sorted()
函数根据 lambda 函数提供的自定义键对points
列表进行排序
lambda x: x[1]
表示列表应根据每个元组的第二个索引中的元素进行排序
2. 使用 lambda 函数根据特定键对字典列表进行排序
>>> students = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}, {'name': 'Charlie', 'age': 20}]
这段代码定义了一个名为 `students` 的列表,其中包含三个字典,每个字典代表一个学生的信息,包括姓名和年龄。
>>> sorted_students = sorted(students, key=lambda x: x['age'])
>>> print(sorted_students)
在这段代码中,我们使用 `sorted` 函数对学生列表 `students` 进行排序,排序的依据是每个学生的年龄(`age`)。通过指定 `key` 参数为一个 `lambda` 函数,我们可以提取出每个学生的年龄作为排序的依据。最后,使用 `print` 函数输出排序后的学生列表 `sorted_students`。
[{'name': '查理', 'age': 20}, {'name': '爱丽丝', 'age': 25}, {'name': '鲍勃', 'age': 30}]
在上面的代码块中:
sorted()
函数根据一个由 lambda 函数提供的自定义排序键对列表students
进行排序
lambda x: x['age']
根据每个学生的年龄以升序计算排序
Lambda 函数和闭包
在 Python 中,闭包 是一个嵌套函数,它可以访问外部函数作用域内的名称和变量,即使外部函数已经执行完毕或返回。可以想象一个背着背包的函数。这个背包里装着函数诞生时环境中的变量,即使那个环境已经不存在。
闭包类似于面向对象编程中的私有变量。它们允许Python程序员将数据与特定行为(函数)捆绑在一起。
以下是Python中闭包的一个简单示例:
# simple_closure.py
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
add_five = outer_function(5)
print(add_five(10))
>>> 15
在上面的 simple_
closure.py
中:
outer_function
通过返回inner_function
定义了一个闭包inner_function
从外部函数的作用域中捕获了变量x
- 当调用
add_five
并传入参数10
时,它将10
加到捕获的x
的值(即5
)上,因此返回15
使用 Lambda 的闭包
Lambda 函数可以作为闭包中的内部函数。这个特性允许 Python 程序员封装需要访问外部函数作用域中变量的行为。
示例
# lambda_closure.py
def outer_function():
x = 10
return lambda y: x + y
add_ten = outer_function()
print(add_ten(5))
>>> 15
在 lambda_
closure.py
中:
lambda y: x + y
作为内部函数- 内部函数从外部函数捕获
x
并将其与y
相加
此外,Python 程序员经常在闭包中使用 lambda 进行简洁的操作。当定义一个单独的函数显得过于繁琐时,这种做法是必要的。
示例
# concise_lambda_closure.py
def outer_function(operation):
return lambda x, y: operation(x, y)
add = outer_function(lambda a, b: a + b)
multiply = outer_function(lambda a, b: a * b)
print(add(3, 5))
print(multiply(3, 5))
>>> 8
>>> 15
在 concise_lambda_
closure.py
中:
outer_function
接受一个函数operation
作为参数- 它返回一个闭包,该闭包将给定的
operation
(add\
和multiply
)应用于其参数x
和y
结论
在本深入教程中,您已经:
- 学习了如何在 Python 程序中使用 lambda 函数
- 了解了 lambda 函数如何帮助简化代码及其在函数式编程中的作用
- 探索了 lambda 函数的简单和高级用例
Lambda 函数就像快速的厨房小窍门。它们是针对特定任务的临时解决方案,类似于烹饪中的即兴发挥。常规的 Python 函数则像是流行的食谱——结构化且可重用。两者都是必不可少的。你需要了解它们以及何时使用它们。