专业编程基础技术教程

网站首页 > 基础教程 正文

什么是 Python 中的 Lambda?

ccvgpt 2025-02-06 14:11:44 基础教程 1 ℃

如果你刚开始使用 Python,那么理解什么是 lambda 可能会有些混乱。

lambda 也称为匿名函数,这是因为 lambda 没有名称。要在 Python 中定义 lambda,你可以使用关键字 lambda 后跟一个或多个参数、一个冒号 (:) 和一个表达式。

什么是 Python 中的 Lambda?

我们将从一个简单的 lambda 函数示例开始,以熟悉其语法,然后我们将了解 Python lambda 函数如何适用于不同的场景。

如何在 Python 中使用 Lambda

让我们从 lambda 函数的语法开始。

lambda 函数以lambda关键字开头,后跟逗号分隔的参数列表。下一个元素是一个冒号(:),后跟一个表达式

lambda  : 

如你所见,可以在一行中定义一个 lambda 函数。

让我们看一个非常简单的 lambda,它将数字 x(参数)乘以 2:

lambda x : 2*x

运行返回了一个函数对象。有趣的是,当我定义一个 lambda 时,我不需要 return 语句作为表达式的一部分。

如果我在表达式中包含 return 语句会怎样?

我们收到语法错误。所以,不需要在 lambda 中包含 return 。

如何在 Python 中调用 Lambda 函数

我们已经了解了如何定义 lambda,但我们如何调用它呢?

首先,我们将在不将函数对象分配给变量的情况下执行此操作。为此,我们只需要使用括号。

(lambda x : 2*x)(2)

我们将用括号将 lambda 表达式括起来,然后用括号括起我们要传递给 lambda 的参数。

这是我们运行时的输出:

我们还有另一种选择。我们可以将lambda函数返回的函数对象赋值给一个变量,然后使用变量名调用函数。

multiply = lambda x : 2*x
multiply(2)

这是我们运行时的输出:

将多个参数传递给 Lambda 函数

在前面的部分中,我们了解了如何定义和执行 lambda 函数。

我们还看到 lambda 可以有一个或多个参数,让我们看一个有两个参数的例子。

创建一个将参数 x 和 y 相乘的 lambda:

(lambda x, y :  x*y)(2,3)

这是我们运行时的输出:


lambda 是一个IIFE(立即调用的函数表达式)。它基本上是一种表示 lambda 函数在定义后立即执行的方式。

Lambda 函数和常规函数之间的区别

在继续研究如何在 Python 程序中使用 lambda 之前,了解常规 Python 函数和 lambda 之间的关系很重要。

让我们以相乘的例子为例:

lambda x, y :  x*y

我们也可以使用def关键字将其编写为常规函数:

def multiply(x, y):     
    return x*y

与 lambda 形式相比,你会立即注意到三个不同之处:

  1. 使用 def 关键字时,我们必须为我们的函数指定一个名称。
  2. 这两个参数括号括起来。
  3. 我们使用return语句返回函数的结果。

将我们的 lambda 函数分配给一个变量是可选的

multiply_lambda = lambda x, y :  x*y

让我们比较一下这两个函数的对象:

def multiply(x, y):
     return x*y
 
multiply_lambda = lambda x, y :  x*y
print(multiply)
print(multiply_lambda)

从上面的图我们可以看到一个区别:使用 def 关键字定义的函数由名称“multiply”标识,而 lambda 函数由通用 标签标识。

让我们看看type() 函数在应用于这两个函数时返回的内容:

所以,这两个函数的类型是一样的。

可以在 Python Lambda 中使用 If Else 吗?

lambda x: x if x > 2 else 2*x

如果 x 大于 2,则此 lambda 应返回 x,否则应返回 x 乘以 2。
首先,让我们确认它的语法是否正确

测试一下我们的功能:

同时你可以看到,如果我们让 lambda 表达式变得越来越复杂,我们的代码会变得更难阅读。

如何用 Lambda 和 Map 替换 For 循环

在本节中,我们将看到 lambda 在应用于像Python 列表这样的可迭代对象时如何变得非常强大。

让我们从一个标准的 Python for 循环开始,循环遍历字符串列表的所有元素并创建一个新列表,其中所有元素都是大写的。

names = ['Jack', 'Elio', 'Helen']
names_result = []

for name in names:
    names_result.append(name.upper())

这是输出:

现在我们将编写相同的代码,但使用 lambda。为此,我们还将使用一个名为map的 Python 内置函数,其语法如下:

map(function, iterable, ...)

map 函数将另一个函数作为第一个参数,然后是一个可迭代列表。在这个具体的例子中,我们只有一个可迭代对象,即名字列表。

将另一个函数作为参数的函数称为高阶函数。

这听起来可能很复杂,这个例子将帮助你理解它是如何工作的。

那么,map函数有什么作用呢?

map 函数返回一个可迭代对象,它是作为第一个参数传递给可迭代对象的每个元素的函数的结果。

在我们的场景中,我们将作为第一个参数传递的函数将是一个 lambda 函数,它将其参数转换为大写格式作为可迭代的,我们将传递我们的list

map(lambda x: x.upper(), names)

上面执行会返回一个map对象。我们怎样才能取回列表呢?

我们可以将map对象转换为列表

list(map(lambda x: x.upper(), names))

很明显,与我们使用 for 循环的代码相比,使用 map 和 lambda 可以使这段代码更加简洁。

将 Lambda 函数与字典结合使用

我想尝试使用 lambda 函数从字典列表中提取特定字段。

这是很多场景都可以应用的东西,下面是一个列表里面包含字典。

people = [{'firstname':'John', 'lastname':'Ross'}, {'firstname':'Mark', 'lastname':'Green'}]

我又一次可以将 map 内置函数与 lambda 函数一起使用。

lambda 函数将一个字典作为参数并返回 firstname 键的值。

lambda x : x['firstname']

完整的表达式是:

firstnames = list(map(lambda x : x['firstname'], people))

运行输出:

将 Lambda 传递给过滤器内置函数

另一个可以与 lambda 一起使用的 Python 内置函数是filter 函数

下面你可以看到它的语法需要一个函数和一个可迭代对象:

filter(function, iterable)

这里的想法是创建一个表达式,给定一个列表返回一个新列表,其元素匹配 lambda 函数定义的特定条件。

例如,给定一个数字列表,我想返回一个只包含负数的列表。

这是我们将使用的 lambda 函数:

lambda x : x < 0

让我们尝试执行此 lambda 并将几个数字传递给它,以便清楚 lambda 返回的内容。

(lambda x : x < 0)(-1)  # True
(lambda x : x < 0)(3)  # False

我们的 lambda 返回一个布尔值:

  • 如果论证是否定的,则为真。
  • 如果参数为正则为假。

现在,让我们将此 lambda 应用于过滤器函数

numbers = [1, 3, -1, -4, -5, -35, 67]
negative_numbers = list(filter(lambda x : x < 0, numbers))
print(negative_numbers)

我们得到了预期的结果,一个包含所有负数的列表。

Reduce 和 Lambda 如何与列表一起使用

另一个常见的 Python 内置函数是属于functools 模块的reduce 函数

reduce(function, iterable[, initializer])

reduce 函数有什么作用?,reduce函数会对参数迭代器中的元素进行积累。

ruduce函数的定义如下:

functools.reduce(function, iterable[, initializer])

为了在实践中理解它,我们将应用一个简单的 lambda 来计算两个数字的总和到数字列表:

from functools import reduce
reduce(lambda x,y: x+y, [3, 7, 10, 12, 5])

运行输出:

让我们看看我们是否也可以使用 reduce 函数来连接列表中的字符串:

from functools import reduce
reduce(lambda x,y: x + ' ' + y, 
       ['This', 'is', 'a', 'tutorial', 'about', 'Python', 'lambdas'])

运行输出:

应用于类的 Lambda 函数

考虑到 lambda 可以用来代替常规的 Python 函数,我们可以将 lambda 用作类方法吗?

我将定义一个名为 Gorilla 的类,它包含一个构造函数和打印消息的运行方法:

class Gorilla:
    def __init__(self, name, age, weight):
        self.name = name
        self.age = age
        self.weight = weight

    def run(self):
        print('{} starts running!'.format(self.name))

然后我创建了这个类的一个名为 Spartacus 的实例并在其上执行 run 方法:

Spartacus = Gorilla('Spartacus', 35, 150)
Spartacus.run()

输出是:

现在,让我们用 lambda 函数替换 run 方法:

class Gorilla:
    def __init__(self, name, age, weight):
        self.name = name
        self.age = age
        self.weight = weight
    run = lambda self: print('{} starts running!'.format(self.name))

在 Gorilla 类的实例上再次执行 run 方法,会看到输出消息完全相同。

将 Lambda 与排序函数一起使用

sorted 内置函数从可迭代对象返回一个排序列表。

让我们看一个简单的例子,我们将对包含一些行星名称的列表进行排序:

planets = ['saturn', 'earth', 'mars', 'jupiter'] # 排序函数按字母顺序对列表进行排序
sorted(planets)

运行输出:

现在,假设我们要根据不同的标准对列表进行排序,例如每个单词的长度。

为此,我们可以使用额外的参数,它允许在进行任何比较之前提供一个应用于每个元素的函数。

sorted(planets, key=len) 
# ['mars', 'earth', 'saturn', 'jupiter']

在这种情况下,我们使用了 len() 内置函数,这就是行星从最短到最长排序的原因。

那么,lambda 在哪里适合所有这些?

Lambda 是函数,因此它们可以与 key 参数一起使用。

例如,假设我想根据每个行星的第三个字母对我的列表进行排序。

sorted(planets, key=lambda p: p[2]) 
#['jupiter', 'earth', 'mars', 'saturn']

如果我想根据特定属性的值对字典列表进行排序怎么办?

people = [{'firstname':'John', 'lastname':'Ross'}, 
          {'firstname':'Mark', 'lastname':'Green'}]
sorted(people, key=lambda x: x['lastname'])

在此示例中,我们根据姓氏键的值对字典列表进行了排序。

运行输出:

Python Lambda 和错误处理

在我们查看 lambda 和常规函数之间区别的部分中,我们看到了以下内容:

>>> multiply

>>> multiply_lambda
 at 0x1014227a0>

其中 multiply 是一个常规函数,multiply_lambda 是一个 lambda 函数。

如你所见,常规函数的函数对象由名称标识,而 lambda 函数对象由通用 名称标识。

这也使得 lambda 函数的错误处理变得更加棘手,因为 Python 回溯不包括发生错误的函数的名称。

让我们创建一个常规函数并向其传递会导致 Python 解释器引发异常的参数:

def calculate_sum(x, y):
    return x+y

print(calculate_sum(5, 'Not_a_number'))

当我在 Python shell 中运行此代码时,出现以下错误:

>>> def calculate_sum(x, y):
...     return x+y
... 
>>> print(calculate_sum(5, 'Not_a_number'))
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in calculate_sum
TypeError: unsupported operand type(s) for +: 'int' and 'str'

从回溯中我们可以清楚地看到错误发生在 calculate_sum 函数的第 2 行。

现在,让我们用 lambda 替换这个函数:

calculate_sum = lambda x, y: x+y
print(calculate_sum(5, 'Not_a_number'))

输出是:

>>> calculate_sum = lambda x,y: x+y
>>> print(calculate_sum(5, 'Not_a_number'))
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 1, in 
TypeError: unsupported operand type(s) for +: 'int' and 'str'

异常类型和错误消息是一样的,但是这次回溯告诉我们函数 的第 1 行发生了错误。想象一下,如果要你必须在 10,000 行代码中找到正确的行是不是大海捞针。这就是为啥尽可能使用常规函数而不是 lambda 函数的另一个原因。

将可变参数列表传递给 Python Lambda

在本节中,我们将了解如何向 Python lambda 提供可变参数列表。

要将可变数量的参数传递给 lambda,我们可以像使用常规函数一样使用*args :

lambda *args: max(args))(5, 3, 4, 10, 24)

当我们运行它时,我们得到传递给 lambda 的参数之间的最大值:

>>> (lambda *args: max(args))(5, 3, 4, 10, 24)
24

我们不一定要使用关键字 args。重要的是 args 之前的 * 在 Python 中代表可变数量的参数。

让我们通过用数字替换 args 来确认是否是这种情况:

>>> (lambda *numbers: max(numbers))(5, 3, 4, 10, 24)
24

Lambda 函数的更多示例

如果你想在 Python 程序中使用 lambda,这些示例应该会给你更多的想法。

给定一个 Linux 命令列表,只返回以字母“c”开头的命令:

>>> commands = ['ls', 'cat', 'find', 'echo', 'top', 'curl']
>>> list(filter(lambda cmd: cmd.startswith('c'), commands))
['cat', 'curl']

从带空格的逗号分隔字符串返回一个列表,其中包含不带空格的字符串中的每个单词:

>>> weekdays = "monday   , tuesday, wednesday,thursday,   friday,  saturday  ,sunday"
>>> list(map(lambda word: word.strip(), weekdays.split(',')))
['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']

使用 Python range 函数生成数字列表并返回大于四的数字:

>>> list(filter(lambda x: x > 4, range(15)))
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

结论

在本篇文章中,我们了解了什么是 Python lambda,以及如何定义和执行它。

我们浏览了带有一个或多个参数的示例,我们还看到了 lambda 如何返回一个函数对象(不需要 return 语句)。

现在你知道 lambda 也称为匿名函数,因为当你定义它时,你不会将它绑定到一个名称。

此外,分析 Python 中常规函数和 lambda 函数之间的区别有助于我们更好地理解 lambda 的工作原理。

当你的代码中只需要一次时,使用 lambda 函数是很常见的。如果你需要在代码库中多次调用的函数,使用常规函数是避免代码重复的更好方法。

永远记住编写干净的代码是多么重要,任何人都可以快速理解的代码,以防将来出现需要快速修复的错误。

现在你可以在 lambda 表达式和常规函数之间做出选择,做出正确的选择!


如果你发现我的任何文章对你有帮助或者有用,麻烦点赞或者转发。 谢谢!

最近发表
标签列表