Python Lambda函数示例

Python中的Lambda函数是什么?

Python编程中的Lambda函数是一个匿名函数,或者说是一个没有名称的函数。它是一个小的、受限的函数,最多只能包含一行。就像普通函数一样,Lambda函数可以有多个参数和一个表达式。

在Python中,lambda表达式(或lambda形式)用于创建匿名函数。为此,您将使用lambda关键字(就像您使用def来定义普通函数一样)。您在Python中定义的每个匿名函数都将包含3个基本部分:

  • Lambda关键字。
  • 参数(或绑定变量),以及
  • 函数体。

Lambda函数可以有任意数量的参数,但函数体只能包含一个表达式。此外,lambda函数写在一行代码中,也可以立即调用。您将在接下来的示例中看到所有这些。

语法和示例

编写lambda函数的正式语法如下所示:

lambda p1, p2: expression

在这里,p1和p2是传递给lambda函数的参数。您可以根据需要添加任意数量的参数。

但是,请注意,我们不像定义普通函数那样在参数周围使用括号。最后一部分(表达式)是任何有效的Python表达式,它会操作您传递给函数的参数。

示例 1

既然您了解了lambda,让我们尝试一个示例。打开您的IDLE并输入以下内容:

adder = lambda x, y: x + y
print (adder (1, 2))

这是输出

3

代码解释

在这里,我们定义了一个变量,它将保存lambda函数返回的结果。

1. 使用lambda关键字定义匿名函数。

2. x和y是我们传递给lambda函数的参数。

3. 这是函数体,它将我们传入的两个参数相加。请注意,这是一个单一的表达式。您不能在lambda函数的体中编写多个语句。

4. 我们调用函数并打印返回值。

示例 2

这是一个基本的例子,用于理解lambda的基础知识和语法。现在让我们尝试打印一个lambda并查看结果。再次,打开您的IDLE并输入以下内容:

#What a lambda returns
string='some kind of a useless lambda'
print(lambda string : print(string))

现在保存您的文件并按F5运行程序。您应该会看到以下输出。

输出

<function <lambda> at 0x00000185C3BF81E0>

这里发生了什么?让我们仔细看看代码以进一步理解。

代码解释

  1. 在这里,我们定义了一个字符串,您将它作为参数传递给lambda。
  2. 我们声明一个lambda,它调用一个print语句并打印结果。

但是,为什么程序不打印我们传入的字符串呢?这是因为lambda本身返回一个函数对象。在这个例子中,lambda不是被print函数调用,而只是返回函数对象及其存储的内存位置。这就是在控制台打印的内容。

示例3

但是,如果您编写如下程序:

#What a lambda returns #2
x="some kind of a useless lambda"
(lambda x : print(x))(x)

然后按F5运行它,您会看到如下输出。

输出

some kind of a useless lambda

现在,lambda正在被调用,我们传入的字符串会被打印到控制台。但是,那种奇怪的语法是什么,为什么lambda定义被方括号括起来了呢?让我们现在来理解一下。

代码解释

  1. 这是我们在上一个示例中定义的相同字符串。
  2. 在这部分,我们定义了一个lambda并立即调用它,将字符串作为参数传递。这被称为IIFE,您将在本教程的后续部分了解更多关于它的信息。

示例4

让我们看最后一个例子,以了解lambda和普通函数是如何执行的。所以,打开您的IDLE并在一个新文件中输入以下内容:

#A REGULAR FUNCTION
def guru( funct, *args ):
funct( *args )
def printer_one( arg ):
return print (arg)
def printer_two( arg ):
print(arg)
#CALL A REGULAR FUNCTION 
guru( printer_one, 'printer 1 REGULAR CALL' )
guru( printer_two, 'printer 2 REGULAR CALL \n' )
#CALL A REGULAR FUNCTION THRU A LAMBDA
guru(lambda: printer_one('printer 1 LAMBDA CALL'))
guru(lambda: printer_two('printer 2 LAMBDA CALL'))

现在,保存文件并按F5运行程序。如果您没有犯任何错误,输出应该与此类似。

输出

printer 1 REGULAR CALL

printer 2 REGULAR CALL

printer 1 LAMBDA CALL

printer 2 LAMBDA CALL

代码解释

  1. 一个名为guru的函数,它将另一个函数作为第一个参数,并将任何其他参数放在其后面。
  2. printer_one是一个简单的函数,它打印传递给它的参数并返回它。
  3. printer_two与printer_one类似,但没有return语句。
  4. 在这部分,我们调用guru函数并将printer函数和字符串作为参数传递。
  5. 这是实现第四步(即调用guru函数)的语法,但使用了lambda。

在下一节中,您将学习如何将lambda函数与Python中的map()reduce()filter()一起使用。

将lambda与Python内置函数一起使用

Lambda函数为使用Python内置方法执行操作提供了一种优雅而强大的方式。这是可能的,因为lambda函数可以立即调用并作为参数传递给这些函数。

Python Lambda中的IIFE

IIFE代表立即调用的函数执行。这意味着lambda函数一旦定义就可以调用。让我们通过一个例子来理解这一点;启动您的IDLE并输入以下内容:

 (lambda x: x + x)(2)

以下是输出和代码解释:

lambda函数这种立即调用的能力允许您在map()和reduce()等函数中使用它们。这很有用,因为您可能不想再次使用这些函数。

filter()中的lambdas

filter函数用于从一系列元素中选择一些特定元素。序列可以是任何迭代器,如列表、集合、元组等。

将被选中的元素是基于一些预定义的约束。它接受2个参数:

  • 定义过滤约束的函数
  • 一个序列(任何迭代器,如列表、元组等)

例如,

sequences = [10,2,8,7,5,4,3,11,0, 1]
filtered_result = filter (lambda x: x > 4, sequences) 
print(list(filtered_result))

以下是输出:

[10, 8, 7, 5, 11]

代码解释

1. 在第一个语句中,我们定义了一个名为sequences的列表,其中包含一些数字。

2. 在这里,我们声明了一个名为filtered_result的变量,它将存储filter()函数返回的过滤后的值。

3. 一个lambda函数,它对列表中的每个元素运行,如果元素大于4,则返回true。

4. 打印filter函数返回的结果。

map()中的lambdas

map函数用于将特定操作应用于序列中的每个元素。与filter()一样,它也接受2个参数:

  1. 定义对元素执行的操作的函数
  2. 一个或多个序列

例如,这是一个打印给定列表中数字平方的程序:

sequences = [10,2,8,7,5,4,3,11,0, 1]
filtered_result = map (lambda x: x*x, sequences) 
print(list(filtered_result))

输出

 [100, 4, 64, 49, 25, 16, 9, 121, 0, 1]

[KR1]

代码解释

  1. 在这里,我们定义了一个名为sequences的列表,其中包含一些数字。
  2. 我们声明了一个名为filtered_result的变量,它将存储映射后的值。
  3. 一个lambda函数,它对列表中的每个元素运行,并返回该数字的平方。
  4. 打印map函数返回的结果。

reduce()中的lambdas

reduce函数,与map()一样,用于将操作应用于序列中的每个元素。然而,它在工作方式上与map不同。以下是reduce()函数用于计算输出的步骤:

步骤1) 对序列的前2个元素执行定义的运算。

步骤2) 保存此结果。

步骤3) 对保存的结果和序列中的下一个元素执行运算。

步骤4) 重复此过程,直到没有更多元素为止。

它也接受两个参数:

  1. 定义要执行的操作的函数
  2. 一个序列(任何迭代器,如列表、元组等)

例如,这是一个返回列表中所有元素乘积的程序:

from functools import reduce
sequences = [1,2,3,4,5]
product = reduce (lambda x, y: x*y, sequences)
print(product)

这是输出

120

代码解释

  1. 从functools模块导入reduce。
  2. 在这里,我们定义了一个名为sequences的列表,其中包含一些数字。
  3. 我们声明了一个名为product的变量,它将存储reduce后的值。
  4. 一个lambda函数,它对列表中的每个元素运行。根据前面的结果,它将返回该数字的乘积。
  5. 打印reduce函数返回的结果。

为什么要(以及为什么不)使用lambda函数?

正如您将在下一节中看到的,lambda在解释器级别被视为与普通函数相同。从某种意义上说,您可以说lambda为编写返回单个表达式的函数提供了简洁的语法。

但是,您应该知道何时使用lambda是合适的,何时避免使用它们。在本节中,您将了解Python开发者在编写lambda时使用的一些设计原则。

Lambda最常见的用例之一是在函数式编程中,因为Python支持一种称为函数式编程的编程范式(或风格)。

它允许您将一个函数作为参数提供给另一个函数(例如,在map、filter等中)。在这种情况下,使用lambda提供了一种优雅的方式来创建一个一次性函数并将其作为参数传递。

何时不应使用Lambda?

您绝不应在生产环境中编写复杂的lambda函数。对于维护代码的开发人员来说,解密它将非常困难。如果您发现自己正在编写复杂的单行表达式,那么定义一个合适的函数将是一种更优越的做法。作为最佳实践,您需要记住,简单的代码总是比复杂的代码更好。

Lambdas与普通函数

如前所述,lambda是[vV4][J5]没有标识符与之绑定的函数。简单来说,它们是无名函数(因此称为匿名函数)。下表说明了Python中lambda和普通函数之间的区别。

Lambdas

普通函数

语法

lambda x : x + x

语法

def (x) :
return x + x 

Lambda函数在其体中只能有一个表达式。

普通函数在其体中可以有多个表达式和语句。

Lambdas没有与之关联的名称。这就是为什么它们也称为匿名函数。

普通函数必须具有名称和签名。

Lambdas不包含return语句,因为其体是自动返回的。

需要返回值而函数应包含return语句。

这些区别的解释?

Lambda与普通函数之间的主要区别在于,lambda函数仅评估单个表达式并产生一个函数对象。因此,我们可以命名lambda函数的结果并在程序中使用它,就像我们在前面的示例中所做的那样。

上面的示例的普通函数将如下所示:

def adder (x, y):
return x + y 
print (adder (1, 2))

在这里,我们必须为函数定义一个名称,该函数在调用它时返回结果。lambda函数不包含return语句,因为它只有一个总是默认返回的表达式。您甚至不必分配lambda,因为它可以立即调用(请参阅下一节)。正如您将在以下示例中看到的,当我们使用Python的内置函数时,lambda变得特别强大。

但是,您可能仍然想知道lambda与返回单个表达式的函数(如上面的函数)有何不同。在解释器级别,差别不大。这可能令人惊讶,但您在Python中定义的任何lambda函数在解释器中都被视为普通函数。

正如您在图中看到的,当转换为字节码时,这两种定义由Python解释器以相同的方式处理。现在,您不能将函数命名为lambda,因为它被Python保留了,但任何其他函数名称都将产生相同的字节码[KR6]。

摘要

  • Lambda,也称为匿名函数,是小的、受限的函数,不需要名称(即标识符)。
  • Python中的每个lambda函数都包含3个基本部分:
  • Lambda关键字。
  • 参数(或绑定变量),以及
  • 函数体。
  • 编写lambda的语法是:lambda 参数:表达式
  • Lambdas可以有任意数量的参数,但它们不包含在括号中。
  • Lambda在其函数体中只能有一个表达式,该表达式默认返回。
  • 在字节码级别,解释器处理lambda和普通函数的方式差别不大。
  • Lambda通过以下语法支持IIFE:(lambda parameter: expression)(argument)
  • Lambdas通常与以下Python内置函数一起使用:
  • Filter:filter (lambda parameter: expression, iterable-sequence)
  • Map:map (lambda parameter: expression, iterable-sequences)
  • Reduce:reduce (lambda parameter1, parameter2: expression, iterable-sequence)
  • 不要在生产环境中编写复杂的lambda函数,因为这会让代码维护者难以理解。

[J5]我添加了一个表,但还需要解释才能理解这些差异。