lambda 有何用处?[关闭]

2024-11-25 08:49:00
admin
原创
200
摘要:问题描述:我正在尝试弄清楚 Python lambda。这是lambda现实生活中应该被遗忘的那些“有趣”语言项目之一吗?我确信在某些特殊情况下可能需要它,但考虑到它的模糊性,它在未来的版本中被重新定义的可能性(我的假设基于它的各种定义)以及降低的编码清晰度 - 应该避免它吗?这让我想起了 C 类型的溢出(缓...

问题描述:

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

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

这让我想起了 C 类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉就像是技术人员的表演技巧,但对于维护程序员来说却是噩梦。


解决方案 1:

你是在谈论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 函数。我花了一段时间才习惯它们,但最终我明白它们是该语言中非常有价值的一部分。

解决方案 2:

lambda只是 的一种花哨说法function。除了名称之外,它并没有什么晦涩、吓人或神秘之处。当您阅读以下行时,请在脑海中将其替换lambda为:function

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

它只是定义了一个函数x。其他一些语言,例如R,明确地说明了这一点:

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

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

解决方案 3:

两行摘要:

  1. 闭包:非常有用。学习它们,使用它们,爱上它们。

  2. Python 的lambda关键词:不必要,偶尔有用。如果你发现自己用 Python 做任何稍微复杂的事情,那就把它放下,定义一个真正的函数。

解决方案 4:

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

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

解决方案 5:

我怀疑 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、map 或 filter 的删除提出抱怨:它们会保留下来。:-)

我个人的看法:就清晰度而言,lambda 很少值得。通常有一个更清晰的解决方案,不包括 lambda。

解决方案 6:

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来获得相同类型的结果)

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

解决方案 7:

在 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

我想说,即使这确实有效,它也非常糟糕且“不符合 Python 风格”,同样的功能可以用无数其他方式编写,例如:

>>> 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 意味着我们可以整齐地删除参数,而无需定义包装函数。

解决方案 8:

我发现 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_1`plural_rule_2`eval()

解决方案 9:

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

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

解决方案 10:

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

解决方案 11:

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:“使用这个新生函数”

for x in a: "进入 a 中的每个元素"

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

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

现在让我们使用 map,它是同样的东西,但更加中立于语言。Maps 接受 2 个参数:

(一) 一项职能

(二)可迭代

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

因此,使用 map 我们可以得到:

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

如果您掌握了 lambda 和映射,您将能够以简洁的方式操纵数据。Lambda 函数既不晦涩难懂,也不会影响代码的清晰度。不要将难懂的东西与新东西混淆。一旦开始使用它们,您就会发现它们非常清晰。

解决方案 12:

我无法谈论 Python 的 lambda 特定实现,但一般来说,lambda 函数确实非常方便。它们是函数式编程的核心技术(甚至可能是唯一的技术),在面向对象程序中也非常有用。对于某些类型的问题,它们是最佳解决方案,因此绝对不应被遗忘!

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

解决方案 13:

在我看来,其中一件好事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的一个例子。

解决方案 14:

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

几年前,当我开始使用 Python 时,我经常使用 lambda,认为它们很酷,还有列表推导。然而,我编写并维护了一个用 Python 编写的大型网站,该网站有几千个函数点。我从经验中了解到,lambda 可能可以用来制作原型,但与内联函数(命名闭包)相比,除了节省一些按键之外,它没有任何优势,有时甚至没有。

基本上可以归结为几点:

  • 使用有意义的名称明确编写的软件更容易阅读。匿名闭包根据定义不能有一个有意义的名称,因为它们没有名字。出于某种原因,这种简洁性似乎也影响了 lambda 参数,因此我们经常看到这样的例子:lambda x: x+1

  • 重用命名闭包更加容易,因为当有一个名称可以引用它们时,它们可以被多次通过名称引用。

  • 调试使用命名闭包而不是 lambda 的代码更容易,因为名称将出现在回溯中和错误周围。

这足以成为将它们汇总起来并转换为命名闭包的理由。但是,我对匿名闭包还有另外两个不满。

第一个不满仅仅是因为它们只是扰乱语言的另一个不必要的关键词。

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

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

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

我努力编写不包含 lambda 的 Python,并删除所有可见的 lambda。我认为没有 lambda 的 Python 会是一种稍微好一点的语言,但这只是我的看法。

解决方案 15:

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

解决方案 16:

Lambda 与函数式编程风格有着密切的联系。通过将函数应用于某些数据并合并结果来解决问题的理念是 Google 用来实现其大多数算法的。

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

解决方案 17:

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

你只需要换个角度思考。我相信你很快就会爱上它。但如果你只处理 Python,就要小心了。因为 Lambda 不是真正的闭包,所以它不知何故“坏了”:Python 的 Lambda 坏了

解决方案 18:

我刚刚开始学习 Python 并首先遇到了 Lambda——我花了一段时间才弄明白。

请注意,这并不是在谴责任何事。每个人都有自己独特的、不容易做到的事情。

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

不。

我确信在某些特殊情况下可能需要它,但考虑到它的模糊性,

这并不奇怪。我之前工作过的 2 个团队中,每个人都一直使用这个功能。

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

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

并降低了编码清晰度——应该避免吗?

如果你使用得当,这并不会降低清晰度。相反,拥有更多可用的语言结构会增加清晰度。

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

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

解决方案 19:

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

解决方案 20:

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

解决方案 21:

我今天开始阅读 David Mertz 的书《Python 中的文本处理》。虽然他对 Lambda 的描述相当简洁,但第一章中的示例与附录 A 中的解释相结合,让我(终于)对它们产生了浓厚的兴趣,我突然明白了它们的价值。这并不是说他的解释对你有用,我还处于探索阶段,因此除了以下内容之外,我不会尝试补充这些回应:我是 Python 新手,我是 OOP 新手,Lambda 对我来说很费劲。现在我读了 Mertz 的书,我想我明白了它们,我认为它们非常有用,因为我认为它们允许一种更简洁的编程方法。

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

解决方案 22:

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

print 'hi there'

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

解决方案 23:

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

以下是示例:

实现空对象模式:

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

解决方案 24:

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

解决方案 25:

我是 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)

解决方案 26:

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3878  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2714  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   49  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   49  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   49  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用