我在试着找出Python的lambda。lambda是那些在现实生活中应该被遗忘的“有趣”语言项之一吗?
我确信有一些边缘情况可能需要它,但是考虑到它的模糊性,它在未来版本中被重新定义的可能性(我基于它的各种定义的假设)以及降低的编码清晰度——应该避免它吗?
这让我想起了C类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉有点像技术人员的表演,但维护程序员的噩梦。
我在试着找出Python的lambda。lambda是那些在现实生活中应该被遗忘的“有趣”语言项之一吗?
我确信有一些边缘情况可能需要它,但是考虑到它的模糊性,它在未来版本中被重新定义的可能性(我基于它的各种定义的假设)以及降低的编码清晰度——应该避免它吗?
这让我想起了C类型的溢出(缓冲区溢出)——指向顶部变量并重载以设置其他字段值。这感觉有点像技术人员的表演,但维护程序员的噩梦。
当前回答
你可以用lambda做的任何事情,都可以用命名函数或列表和生成器表达式做得更好。
因此,在大多数情况下,在任何情况下您都应该只使用其中一种(可能除了在交互式解释器中编写的草稿代码)。
其他回答
Lambda是一个过程构造函数。你可以在运行时合成程序,尽管Python的lambda不是很强大。请注意,很少有人理解这种编程。
你说的是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函数可能是写出一些东西的最短方法。
Returning a function from another function >>> def transform(n): ... return lambda x: x + n ... >>> f = transform(3) >>> f(4) 7 This is often used to create function wrappers, such as Python's decorators. Combining elements of an iterable sequence with 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' Sorting by an alternate key >>> 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函数。我花了一段时间来适应它们,但最终我明白了它们是语言中非常有价值的一部分。
函数这是一种非官僚化的创建函数的方法。
就是这样。例如,假设你有一个主要函数,需要对值平方。我们来看看传统的方法和的方法
传统的方法:
def main():
...
...
y = square(some_number)
...
return something
def square(x):
return x**2
方式:
def main():
...
square = lambda x: x**2
y = square(some_number)
return something
看到区别了吗?
Lambda函数非常适合用于列表,比如列表推导式或映射。事实上,列表理解是一种使用lambda来表达自己的“python”方式。例:
>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]
让我们看看每个语法元素的含义:
[]:“给我一个清单” X **2:“使用这个新诞生的函数” 对于a中的x: "into each element in a"
很方便吧?创建这样的函数。让我们用lambda重写它:
>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]
现在让我们使用map,这是同样的东西,但更语言中立。Maps有两个参数:
(i)一个功能
(ii)可迭代对象
给你一个列表,其中每个元素它是应用于可迭代对象的每个元素的函数。
使用map,我们会得到:
>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)
如果你掌握了lambdas和映射,你将拥有以简洁的方式操作数据的强大能力。Lambda函数既不晦涩,也不影响代码的清晰性。不要把难的东西和新东西混为一谈。一旦你开始使用它们,你就会发现非常清楚。
在我看来,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:我认为这是所谓的“坦克”的一个例子。
我使用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