为什么使用lambda函数?
我可以find很多东西,告诉我什么是lambda函数,语法是如何工作的,什么不是。 但除了“酷炫的因素”(我可以在中间调用另一个函数,很整洁!)我还没有看到过分强烈的说法,为什么我真的需要/想要使用它们。
在我看到的大多数例子中,它似乎更像是一种风格或结构的select。 在python规则中,打破了“只有一个正确的做法”。 它是如何使我的程序更正确,更可靠,更快,更容易理解? (我所见过的大多数编码标准都倾向于告诉你避免在单一行上写出过于复杂的语句,如果这样可以更容易地阅读它。
这是一个很好的例子:
def key(x): return x[1] a = [(1, 2), (3, 1), (5, 10), (11, -3)] a.sort(key=key)
与
a = [(1, 2), (3, 1), (5, 10), (11, -3)] a.sort(key=lambda x: x[1])
从另一个angular度来看:Lambdaexpression式也被称为“匿名函数”,并且在某些编程范例中非常有用,特别是函数式编程,lambda演算为其提供了灵感。
在某些情况下,语法更简洁,主要是在处理map
等时。
map(lambda x: x * 2, [1,2,3,4])
对我来说比对我好:
def double(x): return x * 2 map(double, [1,2,3,4])
在这种情况下,我认为lambda是一个更好的select,因为def double
似乎与使用它的map
几乎断开了。 另外,我想它还有额外的好处,当你完成后,该function将被抛弃。
lambda有一个缺点,它限制了它在Python中的有用性,在我看来:lambdaexpression式只能有一个expression式(即,不能有多行)。 它不能用强制空白的语言工作。
另外,每当我使用lambda我感觉真棒。
Lambda函数在callback函数或需要一次性函数的地方非常有用。 JAB的例子是完美的 – 它最好伴随着关键字参数key
,但它仍然提供有用的信息。
什么时候
def key(x): return x[1]
出现300线以外
[(1,2), (3,1), (5,10), (11,-3)].sort(key)
钥匙是做什么的? 真的没有迹象。 你可能有某种猜测,特别是如果你熟悉这个function的话,通常需要回头看看。 OTOH,
[(1,2), (3,1), (5,10), (11,-3)].sort(lambda x: x[1])
告诉你更多。
- sorting采用一个函数作为参数
- 该函数需要1个参数(和“返回”结果)
- 我试图按列表中每个元素的第二个值对这个列表进行sorting
- (如果列表是一个variables,所以你不能看到值),这个逻辑期望列表中至less有2个元素。
可能还有一些更多的信息,但是已经有了大量的数据,只要使用匿名lambda函数而不是命名函数即可。
另外它不污染你的名字空间;)
对我来说,这是代码的performance力问题。 在编写人们必须支持的代码时,代码应该尽可能简洁易懂地讲述故事。 有时候lambdaexpression式更复杂,有时候它更直接地告诉那行代码块在干什么。 写作时使用判断。
把它想像成一个句子。 什么是重要的部分(名词和动词与对象和方法等),以及如何订购这些行或代码块以直观地expression它正在做的事情。
忽略一点,我们正在谈论的具体匿名函数的细节。 函数(包括匿名函数)在Python中是可赋值的量(几乎不是真正的值)。 一个expression式
map(lambda y: y * -1, range(0, 10))
明确地提到了四个匿名数量:-1,0,10和lambda运算符的结果,再加上map
调用的隐含结果。 可以在某些语言中创build匿名types的值 。 所以忽略function和数字之间的表面上的区别。 使用匿名函数而不是命名函数的问题类似于何时在代码中放置裸数字文字以及何时事先声明TIMES_I_WISHED_I_HAD_A_PONY
或BUFFER_SIZE
。 有些时候使用(数字,string或函数)文字是合适的,有些时候更适合于命名这样的事物并通过其名称来引用它。
见例如 Allen Holub的关于Javadevise模式的挑衅,思想或愤怒的书, 他使用匿名类很多。
是的,你是对的 – 这是一个结构select。 通过使用lambdaexpression式,可能不会使程序更加正确。 它也不会使它们更可靠,这与速度无关。
这只是关于灵活性和expression的力量。 像列表理解。 你可以做大部分的定义命名函数(可能污染命名空间,但这又是纯粹的风格问题)。
它可以有助于可读性,因为你不必定义一个单独的命名函数,其他人将不得不查找,阅读和理解它所做的就是在其参数上调用一个方法blah()。
当你使用它来编写创build和返回其他函数的函数时,可能会更加有趣,这些函数究竟在哪里取决于它们的参数。 这可能是参数化代码行为的非常简洁和可读的方式。 你可以expression更有趣的想法。
但这仍然是一个结构select。 否则你可以这样做。 但是面向对象编程也是如此;)
我学习了lambda函数的一个用法,哪里不是其他好的替代方法呢,或者至less找我最好的是作为函数参数的默认动作
parameter=lambda x: x
这将返回值而不会改变,但您可以select提供一个函数来执行转换或操作(如打印答案,不仅返回)
通常在sorting中使用key也是很有用的:
key=lambda x: x[field]
效果是按顺序sorting每个项目的fieldth(零基记忆)元素。 为了逆转你不需要lambda,因为它更清晰的使用
reverse=True
通常做新的实际function和使用lambda代替lambda一样简单。 如果人们已经学习了很多Lisp或其他函数式编程,他们也有使用lambda函数的自然倾向,如Lisp函数定义由lambda演算处理。
Lambda虽然在某些情况下很有用,却有很大的滥用潜力。 lambda几乎总是使代码更难以阅读。 尽pipe将所有代码放在一行代码中可能会让人感到满意,但它会吸引下一个必须阅读代码的人。
直接从PEP8
“Guido的一个重要见解就是代码的读取次数要比写入代码的次数多得多。”
Lambdas是对象,而不是方法,它们不能像方法那样被调用。 例如
succ = ->(x){ x+1 }
succ mow拥有一个Proc对象,我们可以像其他的一样使用它:
succ.call(2)
给我们一个输出= 3
在某些情况下,将简单的lambdaexpression式expression得更加清晰。 考虑常规的sorting与反向sorting,例如:
some_list = [2, 1, 3] print sorted(some_list) print sorted(some_list, lambda a, b: -cmp(a, b))
对于后一种情况,编写一个单独的完整函数来返回一个-cmp(a, b)
会产生更多的误解,然后lambda。
我想指出一个除了lambda函数似乎是最佳select的列表处理之外的其他情况:
from tkinter import * from tkinter import ttk def callback(arg): print(arg) pass root = Tk() ttk.Button(root, text = 'Button1', command = lambda: callback('Button 1 clicked')).pack() root.mainloop()
如果我们在这里放弃lambda函数,callback函数只能执行一次callback函数。
ttk.Button(root, text = 'Button1', command = callback('Button1 clicked')).pack()
还有一点是python没有switch语句。 结合lambdas和字典可以是一个有效的select。 例如:
switch = { '1': lambda x: x+1, '2': lambda x: x+2, '3': lambda x: x+3 } x = starting_val ans = expression new_ans = switch[ans](x)
Lambda允许您即时创buildfunction。 我所见过的大多数例子都没有做更多的事情,而是创build一个在创build时通过参数而不是执行的函数。 或者他们通过不要求在使用前正式声明函数来简化代码。
一个更有趣的用法是dynamic构造一个python函数来计算直到运行时(用户input)才知道的mathexpression式。 一旦创build,该函数可以重复调用不同的参数来评估expression式(比如说你想绘制它)。 这可能是一个糟糕的例子给予eval()。 这种types的用途是“真正的”力量所在 – 在dynamic地创build更复杂的代码,而不是简单的例子,你经常看到哪些不是很好(源)代码大小减less。