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>
这里发生了什么?让我们仔细看看代码以进一步理解。
代码解释
- 在这里,我们定义了一个字符串,您将它作为参数传递给lambda。
- 我们声明一个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定义被方括号括起来了呢?让我们现在来理解一下。
代码解释
- 这是我们在上一个示例中定义的相同字符串。
- 在这部分,我们定义了一个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
代码解释
- 一个名为guru的函数,它将另一个函数作为第一个参数,并将任何其他参数放在其后面。
- printer_one是一个简单的函数,它打印传递给它的参数并返回它。
- printer_two与printer_one类似,但没有return语句。
- 在这部分,我们调用guru函数并将printer函数和字符串作为参数传递。
- 这是实现第四步(即调用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个参数:
- 定义对元素执行的操作的函数
- 一个或多个序列
例如,这是一个打印给定列表中数字平方的程序:
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]
代码解释
- 在这里,我们定义了一个名为sequences的列表,其中包含一些数字。
- 我们声明了一个名为filtered_result的变量,它将存储映射后的值。
- 一个lambda函数,它对列表中的每个元素运行,并返回该数字的平方。
- 打印map函数返回的结果。
reduce()中的lambdas
reduce函数,与map()一样,用于将操作应用于序列中的每个元素。然而,它在工作方式上与map不同。以下是reduce()函数用于计算输出的步骤:
步骤1) 对序列的前2个元素执行定义的运算。
步骤2) 保存此结果。
步骤3) 对保存的结果和序列中的下一个元素执行运算。
步骤4) 重复此过程,直到没有更多元素为止。
它也接受两个参数:
- 定义要执行的操作的函数
- 一个序列(任何迭代器,如列表、元组等)
例如,这是一个返回列表中所有元素乘积的程序:
from functools import reduce sequences = [1,2,3,4,5] product = reduce (lambda x, y: x*y, sequences) print(product)
这是输出
120
代码解释
- 从functools模块导入reduce。
- 在这里,我们定义了一个名为sequences的列表,其中包含一些数字。
- 我们声明了一个名为product的变量,它将存储reduce后的值。
- 一个lambda函数,它对列表中的每个元素运行。根据前面的结果,它将返回该数字的乘积。
- 打印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]我添加了一个表,但还需要解释才能理解这些差异。