lambda 有什么用?[已结束]

How are lambdas useful? [closed]

提问人:meade 提问时间:5/21/2009 最后编辑:martineaumeade 更新时间:12/19/2021 访问量:586799

问:


想改进这个问题吗?通过编辑这篇文章来更新问题,使其仅关注一个问题。

8年前关闭。

我正在尝试弄清楚 Python lambda。在现实生活中,那些“有趣”的语言项目之一应该被遗忘吗?lambda

我敢肯定,在一些边缘情况下可能需要它,但考虑到它的模糊性,它在未来版本中被重新定义的可能性(我基于它的各种定义的假设)以及降低的编码清晰度 - 应该避免吗?

这让我想起了 C 类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉像是一种技术表演,但维护编码员的噩梦。

Python 函数 lambda 闭包

评论

274赞 Kieveli 2/23/2010
+1 好问题 - 糟糕的假设(lambda 的晦涩难懂)=) 尽量不要对编程技术进行评判。评估它们,并将它们添加到您的心理工具包中。如果你不喜欢它们,就不要使用它们,并准备好在不变得虔诚的情况下合乎逻辑地讨论它们。
0赞 phuclv 11/21/2017
为什么要使用 lambda 函数?

答:

17赞 rmeador 5/21/2009 #1

我不能说 python 的 lambda 特定实现,但总的来说 lambda 函数真的很方便。它们是函数式编程的核心技术(甚至可能是 THE 技术),它们在面向对象的程序中也非常有用。对于某些类型的问题,它们是最好的解决方案,所以当然不应该忘记!

我建议你阅读闭包和 map 函数(链接到 python 文档,但它几乎存在于所有支持函数式构造的语言中),以了解它为什么有用。

评论

3赞 Brian 5/21/2009
这些东西可以在没有 lambda 的情况下完成。这只是一个很大的麻烦。
25赞 Aaron Maenpaa 5/21/2009 #2

几乎所有你可以用你做的事,你都可以用命名函数或列表和生成器表达式做得更好。lambda

因此,在大多数情况下,您基本上在任何情况下都应该只使用其中之一(除了在交互式解释器中编写的临时代码)。

评论

3赞 S.Lott 5/21/2009
“在大多数情况下,你基本上在任何情况下都应该只是其中之一”时期。在解释器中键入 lambda 甚至没有那么有用。
1赞 Javier 5/21/2009
Lambda 是那些难以过度使用的罕见功能之一。只要你能使用它,它就会提高可读性和可维护性。唯一的必要条件是真正了解闭包。如果你不理解它们,你就会相信这个答案这样的废话。
11赞 Aaron Maenpaa 5/21/2009
@Javier 如果您谈论的是“lambda”这个概念,我同意你的看法;但是,如果我们谈论的是 Python 关键字“lambda”,那么:1) 命名函数速度更快,几乎可以执行更多操作(语句 + 表达式) 几乎任何使用 lambda (map+filter) 的地方,您都可以生成表达式或列出性能更高、更简洁的推导式。我并不是说第一类函数不酷,只是 python 中的“lambda”关键字不如仅使用命名函数好,仅此而已。
5赞 Rick Copeland 5/21/2009
lambda 对我来说是必不可少的,可以与采用回调参数的函数一起使用,例如 sort() 和 sorted() 的 key= 参数
20赞 Aaron Maenpaa 5/22/2009
@Rick 我不怀疑这一点,但现实情况是,如果你看到“lambda”,你想到“zohmygod lambda”并开始用 python 编写方案代码,你会对 python 的 lambda 表达式的局限性感到失望。另一方面,如果你开始对自己说“列表理解会起作用吗?不。我需要的东西会从命名函数中受益吗?不。好吧,好吧:sorted(xs, key = lambda x: x.name, x.height)“,您最终可能会使用正确的 lambda 次数。
63赞 rhettg 5/21/2009 #3

我怀疑 lambda 会消失。 请参阅 Guido 关于最终放弃尝试删除它的帖子。另请参阅冲突的概述

你可以看看这篇文章,了解更多关于 Python 功能特性背后的交易历史: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

奇怪的是,最初促使引入 lambda 和其他功能特性的 map、filter 和 reduce 函数在很大程度上已被列表推导式和生成器表达式所取代。事实上,在 Python 3.0 中,reduce 函数已从内置函数列表中删除。(但是,没有必要发送有关删除 lambda、map 或过滤器的投诉:它们会留下来。

我自己的两分钱:就清晰度而言,很少有 lambda 值得。通常,有一个更明确的解决方案不包括 lambda。

评论

2赞 Paweł Polewicz 5/21/2009
请注意,在 Python 3.0 中,reduce 仍然可以导入。如果你真的想要它,你仍然可以拥有它。
8赞 Yogi 5/21/2009 #4

Lambda 通常与函数式编程风格密切相关。您可以通过将函数应用于某些数据并合并结果来解决问题的想法是谷歌用来实现其大部分算法的想法。

以函数式编程风格编写的程序很容易并行化,因此在现代多核机器中变得越来越重要。 所以简而言之,不,你不应该忘记他们。

7赞 Norbert Hartl 5/21/2009 #5

首先恭喜你设法弄清楚了lambda。在我看来,这是一个非常强大的结构。如今,函数式编程语言的趋势无疑是一个指标,表明它既不应该被避免,也不会在不久的将来被重新定义。

你只需要想一点不同。我相信很快你会喜欢它。但是,如果您只处理python,请小心。因为 lambda 不是一个真正的闭包,所以它以某种方式被“破坏”了:pythons lambda 被破坏了

评论

0赞 Brian 5/21/2009
Python 的 lambda 没有被破坏。有两种方法可以在 lambda 中处理局部变量。两者都有优点和缺点。我认为 Python(和 C#)所采用的方法对于那些更习惯于纯函数式语言的人来说可能是违反直觉的,因为对于纯函数式语言,我认为这种方法甚至没有意义。
0赞 Norbert Hartl 5/21/2009
这确实有悖常理。我不是 python 程序员,但在吱吱作响的闲聊中是一样的,我经常遇到这种情况。所以即使我也会认为它“坏了”:)
0赞 Antti Haapala -- Слава Україні 2/27/2013
不,这与反直觉无关。只是变量名的词法范围是函数的词法范围;循环不引入词法作用域。函数在 Javascript 中的工作方式也相同。如果您需要 var 的作用域,您可以随时执行 (lambda scopedvar: lambda x: scopedvar + x)()
19赞 Matt Schmidt 5/21/2009 #6

我已经使用 Python 几年了,我从来没有遇到过需要 lambda 的情况。真的,正如教程所述,它只是为了语法糖。

评论

8赞 Bryan Oakley 4/25/2011
在使用 python 开发 GUI 时,它们非常有用。通常,小部件需要对函数的引用。如果您需要一个小部件来调用函数并传递参数,lambda 是一种非常方便的方法。
1赞 dter 7/4/2016
与将多个参数传递到函数中相比,有什么优势?func_name(a,b):返回 a+b 而不是使用 lambda
2赞 phuclv 7/10/2017
它不是必需的,但它有助于在许多情况下编写更短的代码和更易读的代码,尤其是在 Java 或 C++ 等详细语言中
73赞 egaga 5/21/2009 #7

lambda 是一个非常重要的抽象机制的一部分,它处理高阶函数。为了正确理解它的价值,请观看 Abelson 和 Sussman 的高质量课程,并阅读 SICP 一书

这些都是现代软件业务中的相关问题,并且变得越来越流行。

评论

2赞 Dan Esparza 5/21/2009
Lambda 表达式在其他语言(如 C#)中也越来越流行。他们哪儿也不去。阅读闭包将是理解 Lambda 的有用练习。闭包使许多编码魔术在像jQuery这样的框架中成为可能。
3赞 Gareth Latty 11/19/2014
不要混淆 s 和一等函数。Python 的语句非常有限,但完全是一流的函数。它唯一的区别是你必须命名你想传递的函数。lambdalambda
1059赞 David Z 5/21/2009 #8

你说的是 lambda 表达式吗?喜欢

lambda x: x**2 + 2*x - 5

这些东西实际上非常有用。Python 支持一种称为函数式编程的编程风格,您可以在其中将函数传递给其他函数来执行操作。例:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

设置为 ,原始列表中的那些元素是 3 的倍数。这比mult3[3, 6, 9]

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

当然,在这种特殊情况下,您可以执行与列表推导相同的操作:

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(甚至作为 ),但还有许多其他更复杂的使用案例,您不能使用列表推导式,而 lambda 函数可能是写出某些内容的最短方法。range(3,10,3)

  • 从另一个函数返回一个函数

      >>> def transform(n):
      ...     return lambda x: x + n
      ...
      >>> f = transform(3)
      >>> f(4)
      7
    

    这通常用于创建函数包装器,例如 Python 的装饰器。

  • 将可迭代序列的元素与reduce()

      >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
      '1, 2, 3, 4, 5, 6, 7, 8, 9'
    
  • 按备用键排序

      >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
      [5, 4, 6, 3, 7, 2, 8, 1, 9]
    

我经常使用 lambda 函数。我花了一段时间来适应它们,但最终我开始明白它们是语言中非常有价值的部分。

评论

31赞 etlds 8/31/2016
喜欢这些例子,非常容易理解。但是对于减少部分。如果我必须实现此功能。我会的','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
4赞 Gerard 10/20/2016
顺便说一句,如果您在 Python3 上运行它,您需要在过滤器结果上调用列表以查看实际值,您还需要从 functools 导入 reduce
0赞 stdout 2/7/2017
我们确定上面“函数式编程”的定义吗?这让我有点困惑。
4赞 Chris_Rands 12/8/2017
我认为关键点是函数可以是匿名的(就像在你所有的示例中一样)。如果你将一个函数分配给任何东西,那么你就做错了,应该改用lambdalambdadef
1赞 David Z 12/9/2017
@zgulser 这不是一个定义,它只是关于函数式编程允许你做的事情的陈述。
2赞 Nick Dandoulakis 5/21/2009 #9

Lambda 是一个过程构造函数。您可以在运行时合成程序,尽管 Python 的 lambda 不是很强大。请注意,很少有人理解这种编程。

6赞 Ken 5/21/2009 #10

我刚刚开始使用 Python,并首先进入了 Lambda——这花了我一段时间才弄清楚。

请注意,这不是对任何事情的谴责。每个人都有不同的事情,这些事情来之不易。

lambda 是现实生活中应该被遗忘的“有趣”语言项目之一吗?

不。

我敢肯定,在一些边缘情况下可能需要它,但考虑到它的晦涩难懂,

它并不晦涩难懂。在我工作过的过去 2 个团队中,每个人都一直在使用这个功能。

它在未来版本中被重新定义的潜力(我基于它的各种定义的假设)

除了几年前修复闭包语义之外,我还没有看到在 Python 中重新定义它的严肃建议。

以及降低的编码清晰度 - 应该避免吗?

如果你用得对,这也不是不太清楚。相反,拥有更多的语言结构可以提高清晰度。

这让我想起了 C 类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值......有点像技术表演,但维护编码员的噩梦......

Lambda 就像缓冲区溢出?哇。如果您认为 lambda 是“维护噩梦”,我无法想象您如何使用 lambda。

评论

5赞 Paweł Polewicz 5/21/2009
-1 让我(和其他人)再次阅读整个问题。请注意,其他人设法回答而没有这样做。
4赞 Piotr Czapla 5/21/2009 #11

我经常使用它,主要是作为 null 对象或将参数部分绑定到函数。

以下是示例:

要实现 null 对象模式,请执行以下操作:

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

对于参数绑定:

假设我有以下 API

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

然后,当我不想快速将接收到的数据转储到文件中时,我会这样做:

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()
109赞 John Fouhy 5/21/2009 #12

两行总结:

  1. 闭合:非常有用。学习它们,使用它们,爱它们。
  2. Python 的关键词:不必要的,偶尔有用的。如果你发现自己用它做任何远程复杂的事情,把它收起来,定义一个真正的函数。lambda

评论

1赞 JamesTheAwesomeDude 4/4/2021
对于那些对给出的闭包定义感到困惑的人,这里有一个外行的解释:闭包是指在运行时定义函数的一些变量,但在调用它之前。对于 Python 示例: — 在本例中,将是 的闭包。它捕获它,并将返回它的操作数加上 即使您在不同或未定义的范围内使用它(例如,如果您这样做了)!a = int(input("Enter a number:\n> ")); add=(lambda x: a+x); b = int(input("Enter another number:\n> ")); print("The sum of these numbers is", add(b))faaaimport f from this_comment
5赞 PyNEwbie 5/21/2009 #13

我今天开始阅读 David Mertz 的书《Python 中的文本处理》。虽然他对 Lambda 的描述相当简洁,但第一章中的例子与附录 A 中的解释相结合,使它们(最终)为我跳出了页面,突然间我明白了它们的价值。这并不是说他的解释对你有用,我仍处于发现阶段,所以我不会尝试添加这些回复,除了以下内容: 我是 Python 新手 我是 OOP 的新手 Lambda 对我来说是一场斗争 现在我读了 Mertz,我想我明白了,我认为它们非常有用,因为我认为它们允许更简洁的编程方法。

他再现了 Python 的禅宗,其中一行是“简单胜于复杂”。作为一个非 OOP 程序员,使用 lambda 阅读代码(直到上周列表理解),我一直认为——这很简单?我今天终于意识到,实际上这些特性使代码比替代方案更具可读性和可理解性——后者总是某种循环。我还意识到,就像财务报表一样,Python 不是为新手用户设计的,而是为想要接受教育的用户设计的。我简直不敢相信这种语言有多强大。当我(终于)意识到 lambda 的目的和价值时,我想撕毁大约 30 个程序,并在适当的地方重新开始放入 lambda。

41赞 dbr 5/21/2009 #14

在 Python 中,只是一种定义内联函数的方式,lambda

a = lambda x: x + 1
print a(1)

和。。

def a(x): return x + 1
print a(1)

..是完全一样的

你不能用 lambda 做任何事情,你不能用常规函数做——在 Python 中,函数和其他任何东西一样是一个对象,而 lambda 只是定义一个函数:

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

老实说,我认为这个关键字在 Python 中是多余的——我从来没有需要使用它们(或者看到过一个使用常规函数、列表推导或许多内置函数之一可以更好地使用)lambda

举一个完全随机的例子,来自文章“Python 的 lambda 坏了!

要查看 lambda 是如何被破坏的,请尝试生成一个函数列表,其中 .第一次尝试:fs=[f0,...,f9]fi(n)=i+n

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

我认为,即使这确实有效,它也是可怕的和“非pythonic”的,相同的功能可以用无数其他方式编写,例如:

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

是的,这是不一样的,但我从未见过需要在列表中生成一组 lambda 函数的原因。这在其他语言中可能有意义,但 Python 不是 Haskell(或 Lisp,或......

请注意,我们可以使用 lambda 并仍然达到所需的效果 结果如下:

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

编辑:

在一些情况下,lambda 很有用,例如,在 PyQt 应用程序中连接信号时,它通常很方便,如下所示:

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

这样做会使用额外的参数调用该方法并导致错误。使用 lambda 意味着我们可以整齐地删除参数,而无需定义包装函数。w.textChanged.connect(dothing)dothingevent

评论

2赞 Antti Haapala -- Слава Україні 2/27/2013
您的“lambda 已损坏”参数已损坏,因为 Python 变量范围规则以这种方式工作,句点。如果您在 for-loop 中创建了一个闭包,您将以同样的方式被咬伤。
1赞 Stefan Gruenwald 11/1/2014
lambda 只是 Python 为用户提供“匿名”函数的方式,就像许多其他语言(例如 JavaScript)一样。
1赞 mike3996 11/6/2014
您定义的 lambda 和函数并不完全相同。:)它们至少在不同领域有所不同......a__name__
1赞 kta 11/28/2015
它不仅仅是一个内联函数。
0赞 Titou 2/2/2017
你关于“在另一种语言中可能有意义”的论点很奇怪。要么有 lambda 的内在品质,要么没有。
402赞 user251650 1/16/2010 #15

lambda只是一种花哨的说法.除了它的名字之外,它没有什么晦涩、令人生畏或神秘的东西。当您阅读以下行时,请在脑海中替换为:functionlambdafunction

>>> f = lambda x: x + 1
>>> f(3)
4

它只是定义了 的函数。其他一些语言,比如 ,明确地说出来:xR

> f = function(x) { x + 1 }
> f(3)
4

你看?这是编程中最自然的事情之一。

评论

12赞 ankush981 7/7/2016
Raymond Hettinger在他的一次演讲中对这个名字表示遗憾,并表示可以通过将其命名为“make function”而不是“lambda”来避免所有混淆。:-)
11赞 Ciprian Tomoiagă 1/29/2017
在脑海中替换 BY 并在最后一个表达式之前添加 returnlambdafunction
4赞 chepner 6/8/2018
@AaronMcMillin 试试 . 表达式和语句都生成对象;只有表达式的语法限制了它可以生成实例。type(lambda x: 3)lambdadeffunctionlambda
6赞 chepner 6/8/2018
@AaronMcMillin 你错过了我的观点。仅仅因为你不能用表达式定义每个函数并不意味着表达式的结果不是函数。lambdalambda
1赞 Darren Lefcoe 11/25/2021
该示例与 相同。然而,一个关键的区别是,lambda 可以写在调用它的同一行代码上。可以说,def - return 方法更清晰。f = lambda x: x + 1def f(x): return(x+1)
13赞 Noufal Ibrahim 1/16/2010 #16

在我看来,它被低估了,其中一件好事是,它是将对简单表单的评估推迟到需要值之前的方式。让我解释一下。lambda

许多库例程的实现使它们允许某些参数是可调用的(lambda 就是其中之一)。这个想法是,实际值将仅在使用它时(而不是在调用它时)计算。一个(人为的)例子可能有助于说明这一点。假设你有一个例程,它将记录一个给定的时间戳。您希望例程使用当前时间减去 30 分钟。你会这样称呼它

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

现在假设实际函数仅在发生特定事件时被调用,并且您希望仅在该时间计算时间戳。你可以这样做

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

假设可以处理这样的可调用对象,它将在需要时对其进行评估,并且您将获得当时的时间戳。log_timestamp

当然还有其他方法可以做到这一点(例如使用模块),但我希望我已经传达了这一点。operator

更新这是一个稍微具体的现实世界示例。

更新 2:我认为这是所谓的 thunk 的一个例子。

35赞 Tor Valamo 1/16/2010 #17

我发现 lambda 对于执行相同操作的函数列表很有用,但适用于不同的情况。

就像Mozilla的复数规则一样:

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

如果你必须为所有这些定义一个函数,你会在它结束时发疯。
此外,使用 、 等函数名称也不好。当你依赖于一个变量函数 id 时,你就需要它。
plural_rule_1plural_rule_2eval()

评论

0赞 Katu 1/13/2022
链接向下,替代 developer.mozilla.org.cach3.com/en/Localization_and_Plurals
11赞 Mike A 10/19/2010 #18

如上所述,Python 中的 lambda 运算符定义了一个匿名函数,而在 Python 中,函数是闭包。重要的是不要将闭包的概念与运算符 lambda 混淆,后者对它们来说只是句法美沙酮。

几年前,当我开始使用 Python 时,我经常使用 lambda,认为它们很酷,还有列表推导。但是,我编写并且必须维护一个用 Python 编写的大型网站,大约有几千个功能点。我从经验中了解到,lambda 可能可以用于原型设计,但除了保存一些键控之外,除了保存一些键控或有时不提供任何内联函数(称为闭包)之外,什么都不提供。

基本上,这归结为几点:

  • 使用有意义的名称显式编写的软件更容易阅读。根据定义,匿名闭包不能具有有意义的名称,因为它们没有名称。出于某种原因,这种简洁性似乎也感染了 lambda 参数,因此我们经常看到像 lambda x: x+1 这样的例子
  • 重用命名闭包更容易,因为当有名称可以引用它们时,它们可以多次被引用。
  • 调试使用命名闭包而不是 Lambda 的代码更容易,因为该名称将出现在回溯中,并出现在错误周围。

这足以将它们四舍五入并将它们转换为命名闭包。但是,我对匿名关闭还有另外两个怨恨。

第一个怨恨只是它们只是另一个不必要的关键字,使语言变得混乱。

第二个怨恨更深,在范式层面上,即我不喜欢他们提倡函数式编程风格,因为这种风格不如消息传递、面向对象或过程风格灵活,因为 lambda 演算不是图灵完备的(幸运的是,在 Python 中,即使在 lambda 中,我们仍然可以打破这个限制)。我觉得 lambdas 推广这种风格的原因是:

  • 有一个隐式返回,即它们看起来“应该”是函数。

  • 它们是另一种更明确、更易读、更可重用和更通用的机制的替代状态隐藏机制:方法。

我努力编写无 lambda 的 Python,并在看到时删除 lambda。我认为没有 lambda 的 Python 会是一种稍微好一点的语言,但这只是我的看法。

评论

1赞 0atman 9/14/2011
"...在 Python 中,函数是闭包”。据我了解,这不太对。闭包是函数,但函数并不总是闭包。函数> lambda x,y:x+y。闭包> lambda x: lambda y: x+y
6赞 Antti Haapala -- Слава Україні 2/27/2013
“因为 lambda 演算不是图灵完备的”是完全错误的,非类型 lambda 演算是图灵完备的,这就是它如此重要的原因。您可以使用 Y 组合器获得递归,Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
0赞 Antti Haapala -- Слава Україні 2/27/2013
此外,如果有人去维基百科阅读图灵完备性,它会说“一个典型的例子是 lambda 演算。
0赞 Tony Suffolk 66 2/16/2015
严重 - 不是图灵完备的 - 这个答案需要认真编辑或撤回。
0赞 typedeaf 2/16/2017
@Marcin Łoś 投了赞成票,因为它坚持 KISS。作为比较,K&R 书中提到,虽然使用赋值作为部分或更大的表达式更紧凑,但它通常不太可读。使用函数式编程模式的潮流是陈词滥调和陈词滥调。说明如何使用它们就足够了,但说它们对于成为称职的开发人员至关重要是过于热心的;完全主观。这个论点类似于C++开发人员,他们认为没有类的语言是原始的,低劣的和不充分的。“图灵完备性”,论点是迂腐的。
61赞 Bryan Oakley 4/25/2011 #19

lambda 在 GUI 编程中非常有用。例如,假设您正在创建一组按钮,并且希望使用单个参数化回调,而不是每个按钮的唯一回调。借助 Lambda,您可以轻松实现此目的:

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(注意:虽然这个问题是专门问的,但你也可以使用functools.partial来得到相同类型的结果)lambda

另一种方法是为每个按钮创建一个单独的回调,这可能会导致重复的代码。

评论

1赞 Rqomey 8/6/2013
这正是我查找 lambda 是什么的原因,但为什么它会起作用,对我来说,它看起来与直接调用函数完全相同(stackoverflow.com/questions/3704568/... )。也许已经晚了,它确实有效,但为什么它有效?
6赞 Bryan Oakley 8/6/2013
@Rqomey:区别在于,在这个例子中,它是在一个循环中定义的;在另一个示例中,参数始终只有一个值。当您添加类似 的东西时,您正在将当前值附加到回调。如果没有它,则在回调中绑定对变量的引用。引用将始终包含变量的最终值,因为回调发生在循环完成运行后的一段时间。valuearg=value
1赞 Gareth Latty 11/19/2014
请注意 functools.partial() 的存在,它允许您以更少的粗鲁(并且没有 )。lambda
0赞 Bryan Oakley 11/19/2014
@Lattyware:为什么它“不那么粗鲁”?使用需要额外的库导入,对于大多数简单情况,lambda 绰绰有余。functools.partial
2赞 Gareth Latty 11/19/2014
partial(my_callback, value)vs - lambda 有更多的 cruft(分配给 arg 然后使用),并且不太清楚意图是什么(您可能在 lambda 中做一些微妙的不同的事情)。导入并不是真正的问题(反正你有一堆,每个文件一次)。代码的最佳判断标准是它的阅读能力,并且比 lambda 更容易阅读。lambda arg=value: my_callback(arg)partial()
5赞 Glueberg 7/14/2011 #20

我可以举个例子,我实际上需要认真对待 lambda。我正在制作一个图形程序,其中使用右键单击文件并为其分配三个选项之一。事实证明,在 Tkinter(我正在编写此内容的 GUI 接口程序)中,当有人按下按钮时,它不能分配给接受参数的命令。因此,如果我选择了其中一个选项并希望我选择的结果是:

print 'hi there'

那就没什么大不了的。但是,如果我需要我的选择有一个特定的细节怎么办。例如,如果我选择选项 A,它会调用一个函数,该函数接受依赖于选项 A、B 或 C 的某个参数,TKinter 无法支持这一点。实际上,Lamda是解决这个问题的唯一选择......

评论

2赞 Jon Coombs 12/2/2014
好吧,想必你本来可以做到的,然后传进去而不是.它只是更多的代码,你必须想出一个名字。def foo...foolambda
6赞 Bentley4 11/3/2012 #21

使用 lambda 的一个有用案例是提高长列表推导的可读性。 在这个例子中,为了清楚起见,它是简短的,但想象一下很长。如果您只使用包含该值的普通值而不是 lambda 版本,则将获得 .loop_dicloop_diciNameError

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

而不是

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]
11赞 varagrawal 5/24/2013 #22

Lambda 实际上是非常强大的结构,它源于函数式编程的思想,在不久的将来,它绝不会轻易被修改、重新定义或删除。它们可以帮助您编写更强大的代码,因为它允许您将函数作为参数传递,从而将函数视为一等公民。

Lambda 确实容易让人感到困惑,但是一旦有了扎实的理解,你就可以编写干净优雅的代码,如下所示:

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

上面的一行代码返回列表中数字的平方列表。当然,您也可以这样做:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

很明显,前一段代码更短,如果您打算仅在一个地方使用 map 函数(或任何将函数作为参数的类似函数),则尤其如此。这也使代码更加直观和优雅。

此外,正如@David Zaslavsky 在他的回答中提到的,列表推导并不总是要走的路,特别是如果你的列表必须从某种晦涩的数学方式获取值。

从更实际的角度来看,lambda 最近对我来说最大的优势之一是 GUI 和事件驱动编程。如果你看一下 Tkinter 中的回调,它们所采取的参数只是触发它们的事件。例如

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

现在,如果你有一些论据要通过怎么办?就像传递 2 个参数来存储鼠标单击的坐标一样简单。您可以像这样轻松地做到这一点:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

现在你可以争辩说这可以使用全局变量来完成,但是你真的想担心内存管理和泄漏,特别是如果全局变量只在一个特定的地方使用?那只是糟糕的编程风格。

简而言之,lambda 很棒,永远不应该被低估。Python lambda 和 LISP lambda 虽然不同(更强大),但你真的可以用它们做很多神奇的事情。

评论

0赞 Sanjay Manohar 4/10/2015
谢谢。我完全不明白你上一个例子。为什么 x 和 y 都在 和 中定义?函数中会发生什么情况?传递的值似乎立即被覆盖了?函数是如何知道的?你能补充一些评论/解释吗?谢谢maindo_something_coolxyevent
0赞 varagrawal 4/10/2015
@SanjayManohar我正在传递 和 作为参数,并在函数中设置它们的值,以说明如何使用 lambda 传递不需要的参数。该函数需要一个参数,用于标识该特定小部件上的 GUI 事件。我建议阅读 Tkinter 的编程模型以获得更清晰的信息。xydo-something-coolwidget.bindevent
0赞 Sanjay Manohar 4/20/2015
我的理解是 tkinter 会调用你的函数作为参数。您的函数接受 3 个参数,但您只传递了 2 个参数,并且 .我错过了什么吗?你测试过这段代码吗?eventdo-something-coolxy
0赞 varagrawal 4/21/2015
因此,lambda 获取 event 参数并将其传递给 。因此需要 3 个参数。这实际上就是 lambda 的工作方式,是的,我已经在应用程序中使用了这段代码,然后发布在这里。:)do-something-cooldo-something-cool
0赞 Jeremy Sorensen 12/20/2016
@SanjayManohar - 对不起,这是很久以后的事情了,但实际上 lambda 只传递了两个变量,所以 do-something-cool 应该只接受两个参数,示例中有一个错误。此外,破折号在函数名称中无效,因此从未测试过此代码。
6赞 balki 10/9/2013 #23

我使用 lambda 来避免代码重复。这将使该功能易于理解 例如:

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

我用临时 lambda 替换它

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)
18赞 Lucas Ribeiro 10/11/2013 #24

Lambda 函数 这是一种创建函数的非官僚方式。

就是这样。例如,假设您有主函数,需要对值进行平方。让我们看看传统的方法和 lambda 方法:

传统方式:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

lambda 方式:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

看到区别了吗?

Lambda 函数非常适合列表,例如列表推导式或映射。事实上,列表理解是一种使用 lambda 表达自己的“pythonic”方式。前任:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

让我们看看语法的每个元素的含义:

[] : “给我一个清单”

x**2 : “使用这个新生的功能”

对于 A 中的 X:“进入 A 中的每个元素”

这很方便吧?创建这样的函数。让我们使用 lambda 重写它:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

现在让我们使用地图,这是一回事,但更中立。Maps 有 2 个参数:

(i) 一个功能

(ii) 可迭代对象

并为您提供一个列表,其中每个元素都是应用于可迭代对象的每个元素的函数。

因此,使用地图,我们将有:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

如果您掌握了 lambda 和映射,您将拥有强大的能力以简洁的方式操作数据。Lambda 函数既不晦涩难懂,也不影响代码的清晰度。不要将困难的东西与新的东西混为一谈。一旦你开始使用它们,你会发现它非常清楚。

4赞 NuclearPeon 1/4/2014 #25

我用于创建包含参数的回调。在一行中编写 lambda 比编写方法来执行相同的功能更干净。lambda

例如:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

与以下情况相反:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb
4赞 Pratik Kulkarni 2/7/2014 #26

我是 python 初学者,所以为了清楚地了解 lambda,我将其与“for”循环进行了比较;在效率方面。 这是代码 (python 2.7) -

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)

评论

6赞 Kevin 2/7/2014
您可能对 timeit 模块感兴趣,它通常比减去值提供更准确的结果。time.time()
2赞 qneill 5/14/2015
嗯,你不需要在 first() 和 second() 开始时重新启动计时器吗?