Python lambda 函数使用方法深度总结
本文深入解析 Python lambda 匿名函数的定义、语法及工作原理。详细演示如何结合 filter、map 和 reduce 高阶函数处理数据,探讨其在 Pandas 中的应用。同时对比普通函数,总结 lambda 在代码简洁性与可读性方面的优缺点,并提供最佳实践建议。
今天我们将深入探讨 Python 中的 lambda 函数,分析其核心优势与潜在局限性。
Let's do it!
什么是 Python 中的 Lambda 函数
lambda 函数是一种匿名函数(即未显式命名),它支持接收任意数量的参数。与普通函数不同,lambda 函数仅能计算并返回一个单一的表达式。
Python 中 lambda 函数的语法结构如下:
lambda 参数:表达式
lambda 函数主要由三个部分组成:
- 关键字 lambda:其作用类似于普通函数定义中的 def。
- 参数部分:支持传递位置参数和关键字参数,用法与普通函数一致。
- 表达式主体:用于处理参数并返回结果。
与普通函数不同,lambda 函数的参数无需使用括号包裹。若包含两个或更多参数,直接使用逗号进行分隔即可。
通常,lambda 函数仅用于计算简短的表达式(理想情况下为单行),且只执行一次,无需后续复用。因此,它常被作为参数传递给高阶函数(即接受其他函数作为参数的函数),例如 Python 内置的 filter()、map() 或 reduce() 等。
Python 中的 Lambda 函数如何工作
下面是一个简单的 lambda 函数示例:
lambda x: x + 1
输出结果:
<function __main__.<lambda>(x)>
上述 lambda 函数接收一个参数,将其值加 1 后返回结果。
它是以下使用 def 和 return 关键字编写的普通函数的简化版本:
def increment_by_one(x):
return x + 1
截至目前,我们的 lambda 函数 lambda x: x + 1 仅创建了一个函数对象,并未返回实际值,这是因为我们没有为参数 x 提供具体的输入值。让我们先定义一个变量,并将其传递给 lambda 函数,观察此时的输出:
a = 2
print(lambda x: a + 1)
输出结果:
<function <lambda> at 0x00000250CB0A5820>
我们的 lambda 函数并未按预期返回数值 3,而是返回了函数对象本身及其内存地址。这表明上述方式并非调用 lambda 函数的正确方法。若要向 lambda 函数传递参数、执行计算并返回结果,应采用以下语法:
(lambda x: x + 1)(2)
输出结果:
3
虽然定义 lambda 函数时参数无需括号包裹,但在调用时,我们需要在 lambda 表达式整体及传入的参数周围加上括号。
上述代码还展示了一个重要特性:使用 lambda 函数可以在创建函数的同时立即执行并获取结果。这种模式被称为立即调用函数表达式(Immediately Invoked Function Expression,简称 IIFE)。
我们可以创建包含多个参数的 lambda 函数,此时在函数定义中需用逗号分隔各参数。执行此类 lambda 函数时,同样需按相同顺序列出对应参数,并用逗号分隔:
(lambda x, y, z: x + y + z)(3, 8, 1)
输出结果:
12
lambda 函数也可用于执行条件判断。下面是一个模拟简单 if-else 逻辑的 lambda 示例:
print((lambda x: x if(x > 10) else 10)(5))
print((lambda x: x if(x > 10) else 10)(12))
输出结果:
10 12
若涉及多个条件(如 if-elif-...-else),则必须进行嵌套处理:
(lambda x: x * 10 if x > 10 else (x * 5 if x < 5 else x))(11)
输出结果:
110
然而,上述写法会导致代码可读性显著下降。
在此类情况下,使用包含完整 if-elif-...-else 结构的普通函数是比 lambda 函数更优的选择。实际上,我们可以将上述示例改写为:
def check_conditions(x):
if x > 10:
return x * 10
elif x < 5:
return x * 5
else:
return x
check_conditions(11)
输出结果:
110
尽管上述普通函数代码行数更多,但其可读性明显优于对应的 lambda 写法。
我们可以将 lambda 函数赋值给一个变量,随后像调用普通函数一样调用该变量:
increment = lambda x: x + 1
increment(2)
输出结果:
3
然而,根据 Python 的 PEP 8 编码风格指南,这种做法被视为不良实践。
使用赋值语句消除了 lambda 表达式相对于显式 def 语句的唯一优势(即嵌入到更大表达式中的能力)。
因此,若确实需要存储函数以供后续使用,建议定义一个等效的普通函数,而非将 lambda 函数赋值给变量。
Lambda 函数在 Python 中的应用
带有 filter() 函数的 Lambda
Python 中的 filter() 函数需要接收两个参数:
- 用于定义过滤条件的函数。
- 该函数作用的可迭代对象。
执行该函数后,我们将得到一个过滤器对象:
lst = [33, 3, 22, 2, 11, 1]
filter(lambda x: x > 10, lst)
输出结果:
<filter at 0x250cb090520>
为了从过滤器对象中获取新的迭代器,且确保原始迭代器中所有满足预定义条件的项都被保留,我们需要将过滤器对象传递给 Python 标准库的相关函数:list()、tuple()、set()、frozenset() 或 sorted()(返回排序后的列表)。
下面示例过滤一个数字列表,仅选择大于 10 的数字,并返回按升序排序的列表:
lst = [33, 3, 22, 2, 11, 1]
sorted(filter(lambda x: x > 10, lst))
输出结果:
[11, 22, 33]
我们无需创建与原始对象类型相同的新可迭代对象,此外还可以将此操作的结果存储在一个变量中:
lst = [33, 3, 22, 2, 11, 1]
tpl = tuple(filter(lambda x: x > 10, lst))
tpl
输出结果:
(33, 22, 11)
带有 map() 函数的 Lambda
我们使用 Python 中的 map() 函数对可迭代对象的每个项目执行特定操作。其语法与 filter() 相同:包含一个要执行的函数和一个适用的可迭代对象。
map() 函数返回一个 map 对象,我们可以通过将该对象传递给相应的 Python 函数(如 list()、tuple()、set()、frozenset() 或 sorted())来获取新的迭代数据。
与 filter() 函数类似,我们可以从 map 对象中提取与原始类型不同的可迭代对象,并将其赋值给变量。
下面示例使用 map() 函数将列表中的每个项目乘以 10,并将映射结果作为赋值给变量 tpl 的元组输出:
lst = [1, 2, 3, 4, 5]
print(map(lambda x: x * 10, lst))
tpl = tuple(map(lambda x: x * 10, lst))
tpl
输出结果:
<map object at 0x00000250CB0D5F40> (10, 20, 30, 40, 50)
map() 和 filter() 函数的一个重要区别是:map() 函数总是返回与原始数据长度相同的迭代结果。因此,由于 pandas Series 对象也是可迭代的,我们可以在 DataFrame 列上应用 map() 函数来创建新列:
import pandas as pd
df = pd.DataFrame({'col1': [1, 2, 3, 4, 5], 'col2': [0, 0, 0, 0, 0]})
print(df)
df['col3'] = df['col1'].map(lambda x: x * 10)
df
输出结果:
col1 col2 0 1 0 1 2 0 2 3 0 3 4 0 4 5 0 col1 col2 col3 0 1 0 10 1 2 0 20 2 3 0 30 3 4 0 40 4 5 0 50
当然,在上述场景中,也可以使用 apply() 函数获得相同的结果:
df['col3'] = df['col1'].apply(lambda x: x * 10)
df
输出结果:
col1 col2 col3 0 1 0 10 1 2 0 20 2 3 0 30 3 4 0 40 4 5 0 50
我们还可以根据特定条件为另一列创建新的 DataFrame 列。对于以下代码,我们可以互换使用 map() 或 apply() 函数:
df['col4'] = df['col3'].map(lambda x: 30 if x < 30 else x)
df
输出结果:
col1 col2 col3 col4 0 1 0 10 30 1 2 0 20 30 2 3 0 30 30 3 4 0 40 40 4 5 0 50 50
带有 reduce() 函数的 Lambda
reduce() 函数与 functools Python 模块相关,其工作原理如下:
- 对可迭代对象的前两项进行操作并保存结果。
- 将保存的结果与可迭代对象的下一项进行操作。
- 以这种方式在值对之间持续操作,直到所有项目处理完毕。
该函数与前两个函数拥有相同的两个参数:一个函数和一个可迭代对象。但与前述函数不同的是,此函数无需传递给其他函数,而是直接返回标量结果值:
from functools import reduce
lst = [1, 2, 3, 4, 5]
reduce(lambda x, y: x + y, lst)
输出结果:
15
上述代码展示了使用 reduce() 函数计算列表总和的过程。
需要注意的是,reduce() 函数始终需要一个包含两个参数的 lambda 函数,且我们必须首先从 functools Python 模块中导入它。
Python 中 Lambda 函数的优缺点
优点
- 它是评估单个表达式的理想选择,且该表达式通常只需评估一次。
- 它可以在定义后立即被调用。
- 与相应的普通语法相比,其语法更加紧凑。
- 它可以作为参数传递给高阶函数,例如 filter()、map() 和 reduce()。
缺点
- 它无法执行多个表达式。
- 它容易变得冗长且可读性差,例如当包含 if-elif-...-else 逻辑时。
- 它不能包含任何变量赋值(例如,lambda x: x=0 将抛出语法错误)。
- 我们无法为 lambda 函数提供文档字符串。
总结
总而言之,我们已经详细讨论了在 Python 中定义和使用 lambda 函数的多个方面:
- lambda 函数与普通 Python 函数的区别。
- Python 中 lambda 函数的语法结构及解析。
- 何时适合使用 lambda 函数。
- lambda 函数的工作原理。
- 如何正确调用 lambda 函数。
- 立即调用函数表达式(IIFE)的定义。
- 如何使用 lambda 函数执行条件操作,如何嵌套多个条件,以及为何应避免这种做法。
- 为何应避免将 lambda 函数赋值给变量。
- 如何将 lambda 函数与 filter() 函数结合使用。
- 如何将 lambda 函数与 map() 函数结合使用。
- 如何在 pandas DataFrame 中使用 lambda 函数。
- 带有传递给它的 lambda 函数的 map() 函数,以及在此场景下使用的替代功能。
- 如何将 lambda 函数与 reduce() 函数结合使用。
- 在普通 Python 代码中使用 lambda 函数的优缺点分析。
希望今天的讨论能使 Python 中看似复杂的 lambda 函数概念更加清晰,更易于实际应用。
以上就是 Python lambda 函数使用方法深度总结的详细内容,更多关于 Python lambda 函数的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













