为什么Python Lambda有用?[关闭]


927

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

我确定在某些情况下可能需要使用它,但是鉴于它的晦涩之处,在将来的版本中重新定义了它的潜力(根据各种定义我的假设)以及降低的编码清晰度-是否应该被避免?

这让我想起了C类型的溢出(缓冲区溢出)-指向顶部变量,并通过重载来设置其他字段值。感觉像是技术娴熟的演艺风格,但却是维护编码员的噩梦。


260
+1好问题-错误的假设(lambda的晦涩感)=)尽量不要对编程技术有判断力。评估它们,并将其添加到您的心理工具包中。如果您不喜欢它们,请不要使用它们,并准备好逻辑地讨论它们而不会变得虔诚。
Kieveli 2010年

41
Haskell规则!Lambda函数为您提供了表现力和抽象能力。
乔纳森·巴贝罗

11
@JAL更不用说LISP ...
ApproachingDarknessFish

8
@啊,那是你父亲的括号。这是一个文明程度更高的武器。-Obi Lisp Kenobi
Fields

Answers:


1007

您是在谈论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])

设置mult3[3, 6, 9],原始列表的那些元素是3的倍数。这比(可能会说清楚)短于

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]

(或什至range(3,10,3)),但是在许多其他更复杂的用例中,您不能使用列表推导,而lambda函数可能是写出东西的最短方法。

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

    >>> 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函数。我花了一些时间来适应它们,但最终我了解到它们是语言中非常有价值的一部分。


26
喜欢这些例子,非常容易理解。但对于减少部分。如果我必须实现此功能。我会做','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
etlds

3
顺便说一句,如果您在Python3上运行此代码,则需要在过滤结果上调用列表以查看实际值,还需要从functools中导入reduce
Gerard

我们确定上面的“函数式编程”的定义吗?这让我有些困惑。
stdout

3
我认为关键是lambda函数可以是匿名的(就像您所有示例中一样)。如果您要lambda为任何东西分配一个函数,那么您就做错了,应该def改用
Chris_Rands

1
@zgulser这不是一个定义,只是关于函数式编程允许您执行的操作的声明。
大卫Z

377

lambda只是一种幻想的表达方式function。除了它的名字,没有什么晦涩,令人生畏或神秘的东西。阅读以下行时,请以替换lambdafunction

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

它只是定义的功能x。其他一些语言(如R)则明确指出:

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

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


36
对于那些来自非编程背景(即精确科学)的人来说,这是一个很好的描述,这使得其含义lambda 非常易于理解。谢谢!
加百利

10
雷蒙德·海廷格(Raymond Hettinger)在一次演讲中对这个名字表示遗憾,并说可以通过将其命名为“ make function”而不是“ lambda”来避免所有混淆。:-)
ankush981 '16

10
在您的头脑中替换lambdafunctionreturn在最后一个表达之前添加
CiprianTomoiagă17年

4
@AaronMcMillin尝试type(lambda x: 3)lambda表达式和def语句都生成function对象;只是lambda表达式的语法限制了它可以产生哪些实例。
chepner

6
@AaronMcMillin您错过了我的观点。只是因为你不能定义一个函数lambda表达式并不意味着结果lambda表达不是一个功能。
chepner

107

两行摘要:

  1. 闭包:非常有用。学习他们,使用他们,爱他们。
  2. Python的lambda关键字:不必要,偶尔有用。如果您发现要使用它进行远程复杂的操作,则将其丢弃并定义一个真正的功能。

72

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

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


1
Lambda表达式也正在其他语言(例如C#)中流行。他们不会去任何地方。阅读闭包对于理解Lambda是有用的练习。在jQuery之类的框架中,闭包使很多编码魔术成为可能。
丹·埃斯帕萨

3
不要混淆lambdas和一流的功能。Python的lambda语句非常有限,但是功能完全一流。唯一的区别是您必须命名要传递的功能。
Gareth Latty

59

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

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

(注意:尽管这个问题是专门询问的lambda,但您也可以使用functools.partial获得相同类型的结果)

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


1
这就是为什么我查找了lambda的原因,但是为什么这样做有效,对我来说,它看起来与直接调用函数完全相同(stackoverflow.com/questions/3704568/…)。也许已经晚了,它确实起作用了,但是为什么它起作用了?
Rqomey

5
@Rqomey:区别在于本例中value是在循环中定义的;在另一个示例中,参数始终只有一个值。当您添加类似的内容时arg=value,您会将当前值附加到回调中。没有它,您就将引用绑定到回调中的变量。该引用将始终包含变量的最终值,因为回调发生在循环已完成运行后的某个时间。
布莱恩·奥克利

1
我昨天刚开始工作,老实说,我不敢相信它有多么有用...我可以从一个用于循环的菜单和一个用于配置的csv文件建立一个菜单。真的很有用。
Rqomey

1
请注意,functools.partial()它的存在使您可以减少工作量(并且没有lambda)。
Gareth Latty

2
partial(my_callback, value)vs lambda arg=value: my_callback(arg)-Lambda有更多的不足之处(分配给arg,然后分配用法),并且目的是不清楚(您可能会在lambda中做一些细微的变化)。导入并不是真正的问题(无论如何,您都有很多,每个文件一次)。最好根据代码的读取程度来判断代码,并且partial()比lambda易于阅读。
Gareth Latty

58

我怀疑lambda会消失。有关最终放弃尝试删除它的信息,请参见Guido的文章。另请参阅冲突概述

您可以查看此帖子,以获得有关Python功能特性背后交易的更多历史记录:http : //python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

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

我自己的2美分:就清晰程度而言,lambda很少值得。通常,有一个更清晰的解决方案,其中不包含lambda。


2
请注意,reduce仍可在Python 3.0中导入。如果您真的想要它,您仍然可以拥有它。
帕维尔Polewicz

我认为Guido的尝试更多是关于语法。此人也认为:cackhanded.com/blog/post/2008/01/24/...
leewz

38

在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'>

老实说,我认为该lambda关键字在Python中是多余的-我从来不需要使用它们(或者看到可以在更适合使用常规函数,列表理解或许多内置函数之一的地方使用)

对于完全随机的示例,请参阅文章“ 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())

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


2
您的“ lambda损坏”参数已损坏,因为python变量作用域规则在周期内以这种方式工作。如果您在for循环中创建了一个闭包,您将以同样的方式被咬。
Antti Haapala

1
就像许多其他语言(例如javascript)一样,lambda只是python为用户提供“匿名”功能的方式。
Stefan Gruenwald,2014年

1
a您定义的lambda和function 并不完全相同。:)他们__name__至少因领域而异...
nperson325681 2014年

1
它的工作不仅仅是内联函数。
kta

您关于“用另一种语言可能有意义”的论点很奇怪。有lambdas的内在品质,或者没有。
Titou

31

我发现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'

如果您必须为所有这些功能定义一个功能,那么到最后它就会让您发疯。
此外,使用函数名称(如plural_rule_1plural_rule_2等)也不是很好。而且eval(),当您依赖于可变函数id时就需要使用它。


1
这看起来类似于到目前为止我在F#中使用模式匹配和选项进行的短暂接触。您是否有更多有关如何使用此语法的信息?

26

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

因此,在大多数情况下,您基本上只应该是在任何情况下都可以选择的一种(可能不是交互式解释器中编写的草稿代码)。


3
“在大多数情况下,您基本上应该只是其中一种”。在解释器中输入lambda甚至没有帮助。
S.Lott

11
@Javier如果您谈论“ lambda”这个概念,我同意您的看法;但是,如果我们在谈论python关键字“ lambda”,则:1)命名函数几乎可以在使用lambdas(map + filter)的任何地方更快并且可以执行更多操作(语句+表达式),您可以生成表达式或列出推导更加高效,简洁。我并不是说一流的函数并不酷,只是python中的“ lambda”关键字不如仅使用命名函数那么好。
亚伦·曼帕

3
lambda对我来说是不可缺少的,因为它需要使用带有回调参数的函数,例如sort()和sorted()的key =参数
Rick Copeland 2009年

19
@Rick我毫不怀疑,但是现实是,如果当您看到“ lambda”并且您认为“ zohmygod lambda”并开始在python中编写方案代码时,您一定会对python的lambda表达式的局限性感到失望。另一方面,如果您开始想自己“列表理解会起作用吗?不会。我需要从命名函数中受益吗?不会。好吧:sorted(xs,key = lambda x:x.name, x.height)”,则您可能最终会以正确的次数使用lambda。
亚伦·曼帕

4
+1:当人们使用lambda时,我无法强调一个人使用无名函数。名称确实具有宝贵的知识附加值。
Stephane Rolland

19

我已经使用Python几年了,但从未遇到过需要 lambda的情况。确实,如本教程所述,它仅用于语法糖。


8
当使用python开发GUI时,它们非常有用。小部件通常需要引用功能。如果您需要一个小部件来调用函数并传递参数,lambda是一种非常方便的方法。
Bryan Oakley

1
将多个参数传递给函数的好处是什么?func_name(a,b):返回a + b而不是使用lambda
dter

2
它并不需要,但它有助于编写短的代码更易读在许多情况下,ESP。使用Java或C ++等冗长的语言
phuclv

17

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

我建议您阅读闭包map函数(链接到python文档,但几乎所有支持功能构造的语言都存在),以了解其有用性。


3
这些东西可以不用lambda来完成。这是一个很大的麻烦。
布赖恩

17

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]

现在让我们使用地图,这是一回事,但是在语言上是中立的。地图采用2个参数:

(i)一个功能

(ii)可迭代

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

因此,使用map我们将拥有:

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

如果您掌握lambda和映射,那么您将拥有以简洁的方式操作数据的强大能力。Lambda函数既不模糊也不使代码清晰。不要将困难与新事物混淆。一旦开始使用它们,您会发现它非常清晰。


13

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

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

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

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

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

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

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

更新是一个更具体的现实示例。

更新2:我认为这是所谓的“ thunk”的示例。


11

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

几年前,当我开始使用Python时,我经常使用lambda,认为它们很酷,而且很理解列表。但是,我编写并必须维护一个用Python编写的大型网站,其功能点约为数千个。我从经验中学到,lambda可以用它们进行原型制作,但是除了保存一些键调用(有时甚至不保存)之外,内联函数(命名为闭包)什么也没有提供。

基本上可以归结为以下几点:

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

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

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

第二个怨恨在范式层次上更深,也就是说,我不喜欢它们提倡一种函数式编程风格,因为这种风格比消息传递,面向对象或过程风格的灵活性差,因为lambda演算不是Turing- complete(幸运的是,在Python中,即使在lambda中,我们仍然可以突破该限制)。我觉得Lambda推广这种风格的原因是:

  • 有一个隐式的回报,即它们似乎“应该”是函数。

  • 它们是另一种更清晰,更易读,更可重用且更通用的机制:方法的状态隐藏机制。

我努力编写无lambda的Python,并删除可见的lambda。我认为如果没有lambda,Python会是一种更好的语言,但这只是我的观点。


1
“ ...在Python函数中是闭包”。据我了解,这不太正确。闭包是函数,但函数并不总是闭包。功能-> lambda x,y:x + y。闭包-> lambda x:lambda y:x + y
0atman 2011年

6
“因为lambda演算不是图灵完备的”是完全错误的,未键入的lambda演算是图灵完成的,这就是它如此重要的原因。您可以使用Y组合器进行递归Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
Antti Haapala

此外,如果有人去Wikipedia阅读有关Turing完整性的文章,它会说“一个经典的例子是lambda演算”。
Antti Haapala

严重-图灵不完整-此答案需要认真编辑或撤消。
托尼·萨福克

@MarcinŁoś投票通过,因为它坚持了KISS。作为比较,K&R书中提到,虽然将赋值用作部分或较大的表达式会更紧凑,但通常可读性较低。使用函数式编程模式的趋势是陈词滥调和陈词滥调。陈述它们的用法就足够了,但是宣称它们对于成为合格的开发人员至关重要,这实在是太过热情了;完全主观的。这种说法类似于C ++开发人员,他们认为没有类的语言是原始的,次等的和不足的。“转向完成”,争论是are腐的。
typedeaf

11

Lambda实际上是非常强大的构造,其源于函数式编程的思想,并且在不久的将来Python绝不会轻易对其进行修改,重新定义或删除。它们可以帮助您编写功能更强大的代码,因为它允许您将函数作为参数进行传递,从而使函数成为一流公民。

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(功能更强大)不同,但是您确实可以用它们做很多神奇的事情。


谢谢。我完全不明白您的最后一个例子。x和y在main和中do_something_cool如何定义?发生什么x,并y在功能?传递的值似乎会立即被覆盖?函数如何得知event?您可以添加一些评论/解释吗?谢谢
Sanjay Manohar

@SanjayManohar我传递x,并y作为参数do-something-cool和它们的值的功能设定,说明了如何使用lambda表达式来传递,其中没有一个是预期的参数。该widget.bind函数需要一个event参数来标识该特定小部件上的GUI事件。我建议阅读Tkinter的编程模型以更清晰。
varagrawal 2015年

嗯,我想我了解Tkinter模型。但是仍然不太理解-你通过了x,y然后做x=event.x。那不会覆盖您传递的值吗?函数如何知道是什么event?我看不到将其传递给函数的位置。还是一种方法?您还可以在函数名称中使用减号吗?
桑杰·马诺哈

@SanjayManohar好友,您需要阅读Tkinter和Python。Tkinter将事件对象作为默认操作传递给该函数。至于x, y,这只是出于说明目的的示例。我试图展示lambda的力量,而不是Tkinter。:)
varagrawal 2015年

1
好吧,现在我明白了您的意图-您希望该函数接收event?在这种情况下,您的lambda不应该阅读lambda event: do_something_cool(event,x,y)吗?
桑杰·马诺哈

8

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

以函数式编程风格编写的程序易于并行化,因此在现代多核计算机中变得越来越重要。简而言之,不,您不应该忘记它们。


7

首先恭喜您找出了lambda。在我看来,这是一个非常强大的构造。如今,趋向于函数式编程语言的趋势无疑表明,既不应该避免也不希望在不久的将来重新定义它。

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


Python的lambda没有坏。在lambda中有两种处理本地人的方法。两者都有优点和缺点。我认为Python(和C#)采用的方法可能与那些更习惯纯函数式语言的人不合常理,因为对于纯函数式语言,我认为这种方法甚至没有道理。
布赖恩

确实是违反直觉的。我不是python程序员,但在吱吱作响的小交谈中是一样的,因此我定期对此进行批评。因此,即使是我也认为它“坏了” :)
Norbert Hartl

不,这与反情报无关。只是变量名的词法范围就是函数的范围。循环不会引入词法作用域。函数在Javascript中的工作方式也相同。如果您需要var的作用域,则可以随时执行(lambda scopedvar:lambda x:scopedvar + x)()
Antti Haapala

6

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

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

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

没有。

我确定在某些情况下可能需要使用它,但是鉴于它的晦涩之处,

这不是晦涩的。我工作的过去2个团队中,每个人都一直使用此功能。

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

除了几年前修复闭包语义外,我还没有认真的提议在Python中重新定义它。

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

如果使用得当,还不清楚。相反,拥有更多可用的语言构造可提高清晰度。

这让我想起了C类型的溢出(缓冲区溢出)-指向顶部变量,并重载了设置其他字段的值。

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


5
-1使我(和其他人)再次阅读整个问题。请注意,其他人设法不回答就回答了。
帕维尔Polewicz

6

我使用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)

5

我今天开始阅读David Mertz的书“ Python中的文本处理”。尽管他对Lambda的描述非常简洁,但结合了附录A中的解释使第一章的示例对我来说(最终)从页面上跳了下来,突然之间我明白了它们的价值。并不是说他的解释对您有用,我仍然处于发现阶段,因此除了以下内容之外,我不会尝试添加其他答复:我是Python新手,还是OOP Lambdas新手。既然我读了Mertz,我想我会得到它们,并且我认为它们非常有用,因为我认为它们允许使用更简洁的编程方法。

他再现了Python的Zen,其中的一句话是简单胜于复杂。作为一个非OOP程序员,使用lambda读取代码(直到上周列出了理解),我曾想过- 这很简单吗?。我今天终于意识到,实际上这些功能使代码比替代方案更具可读性和可理解性,而替代方案始终是某种形式的循环。我还意识到,就像财务报表一样,Python并不是为新手用户设计的,而是为希望受过教育的用户设计的。我不敢相信这种语言有多么强大。当我终于意识到了lambda的目的和价值时,我想撕碎大约30个程序,并在适当的地方重新开始使用lambda。


5

使用lambda的一个有用案例是提高长列表理解的可读性。在此示例中,loop_dic为简洁起见,loop_dic它很短,但可以想象它很长。如果您仅使用包含的纯值i而不是该值的lambda版本,则将获得NameError

>>> 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'}]

5

我可以举一个例子,说明我实际上需要严重的lambda。我正在制作一个图形程序,其中使用权在文件上单击并为其分配三个选项之一。事实证明,在Tkinter(我正在编写的GUI接口程序)中,当有人按下按钮时,无法将其分配给带有参数的命令。因此,如果我选择其中一个选项并希望选择的结果是:

print 'hi there'

那没什么大不了的。但是,如果我需要选择一个特定的细节怎么办?例如,如果我选择选项A,则它调用一个函数,该函数接受依赖于选项A,B或C的某些参数,TKinter不支持此功能。实际上,Lamda是解决此问题的唯一选择。


2
好吧,想必您可以完成工作def foo...,然后再通过foo而不是lambda。这只是更多的代码,您必须提供一个名称。
乔恩·库姆斯

4

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

以下是示例:

实现空对象模式:

{
    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()

4

我用 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

我是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
您可能对timeit模块感兴趣,该模块通常会得出比减去time.time()值更准确的结果。
凯文

2
嗯,您不需要在first()和second()的开头重新启动计时器吗?
qneill 2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.