我在试着找出Python的lambda。lambda是那些在现实生活中应该被遗忘的“有趣”语言项之一吗?
我确信有一些边缘情况可能需要它,但是考虑到它的模糊性,它在未来版本中被重新定义的可能性(我基于它的各种定义的假设)以及降低的编码清晰度——应该避免它吗?
这让我想起了C类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉有点像技术人员的表演,但维护程序员的噩梦。
我在试着找出Python的lambda。lambda是那些在现实生活中应该被遗忘的“有趣”语言项之一吗?
我确信有一些边缘情况可能需要它,但是考虑到它的模糊性,它在未来版本中被重新定义的可能性(我基于它的各种定义的假设)以及降低的编码清晰度——应该避免它吗?
这让我想起了C类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉有点像技术人员的表演,但维护程序员的噩梦。
当前回答
两行总结:
闭包:非常有用。学习它们,利用它们,热爱它们。 Python的lambda关键字:不必要,偶尔有用。如果你发现自己在用它做任何复杂的事情,把它放在一边,定义一个真正的函数。
其他回答
我不能说python对lambda的具体实现,但一般来说lambda函数真的很方便。它们是函数式编程的核心技术(甚至是技术),在面向对象程序中也非常有用。对于某些类型的问题,它们是最好的解决方案,所以当然不应该忘记!
我建议你仔细阅读闭包和map函数(它链接到python文档,但它存在于几乎所有支持函数结构的语言中),看看它为什么有用。
你可以用lambda做的任何事情,都可以用命名函数或列表和生成器表达式做得更好。
因此,在大多数情况下,在任何情况下您都应该只使用其中一种(可能除了在交互式解释器中编写的草稿代码)。
在Python中,lambda只是内联定义函数的一种方式,
a = lambda x: x + 1
print a(1)
和. .
def a(x): return x + 1
print a(1)
..是完全一样的。
你可以用lambda做任何常规函数做不到的事情——Python函数和其他任何东西一样都是对象,lambdas只是定义一个函数:
>>> 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方法并导致错误。使用lambda意味着我们可以整齐地删除参数,而不必定义包装函数。
lambdas在GUI编程中非常有用。例如,假设您正在创建一组按钮,并且希望使用单个参数化回调,而不是每个按钮使用唯一的回调。Lambda让你轻松完成:
for value in ["one","two","three"]:
b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
b.pack()
(注意:虽然这个问题是专门问lambda的,但你也可以使用functools。以获得相同类型的结果)
另一种方法是为每个按钮创建单独的回调,这可能导致重复的代码。
在我看来,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:我认为这是所谓的“坦克”的一个例子。