我可以找到很多东西,向我展示什么是lambda函数,以及语法如何工作以及什么不是。但是除了“凉爽因素”(我可以在中间调用另一个函数,整洁!)之外,我还没有看到任何令人信服的东西来说明为什么我真的需要/想要使用它们。
在我所看到的大多数示例中,这似乎更多是一种风格或结构选择。并且kinda打破了python规则中的“唯一正确的做事方式”。它如何使我的程序更正确,更可靠,更快或更易于理解?(我见过的大多数编码标准都倾向于告诉您避免在一行上写过分复杂的语句。如果这样更易于阅读,请将其分解。)
我可以找到很多东西,向我展示什么是lambda函数,以及语法如何工作以及什么不是。但是除了“凉爽因素”(我可以在中间调用另一个函数,整洁!)之外,我还没有看到任何令人信服的东西来说明为什么我真的需要/想要使用它们。
在我所看到的大多数示例中,这似乎更多是一种风格或结构选择。并且kinda打破了python规则中的“唯一正确的做事方式”。它如何使我的程序更正确,更可靠,更快或更易于理解?(我见过的大多数编码标准都倾向于告诉您避免在一行上写过分复杂的语句。如果这样更易于阅读,请将其分解。)
append
。如果在某些情况下允许一个,则在任何情况下都没有理由反对另一个。
Answers:
这是一个很好的例子:
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])
从另一个角度来看:Lambda表达式也被称为“匿名函数”,并且在某些编程范例(尤其是函数编程)中非常有用,lambda演算为其提供了灵感。
operator.itemgetter(1)
代替lambda x: x[1]
。
import operator
先。@琥珀:谢谢;我不记得我的头顶了,所以只是在谨慎方面犯了错误。
operator
实际上,其中的功能比其lambda的功能快一百倍。
lambda x: x[0]**2 + x[1]**2
在某些情况下,尤其是在与map
et al的交易中,语法更加简洁。
map(lambda x: x * 2, [1,2,3,4])
在我看来比以下更好:
def double(x):
return x * 2
map(double, [1,2,3,4])
我认为在这种情况下,lambda是一个更好的选择,因为它def double
似乎与map
使用它的人几乎脱节了。另外,我猜它还有一个额外的好处,就是当您完成该功能后,该函数将被丢弃。
我认为,lambda有一个缺点,限制了它在Python中的用途:lambda只能有一个表达式(即,不能有多行)。它只是不能在强制使用空格的语言中工作。
另外,每当我使用lambda时,我都会感觉很棒。
[x*2 for x in [1,2,3,4]]
。
map((2).__mul__, [1,2,3,4])
。
Lambda函数在诸如回调函数之类的地方或需要使用一次性函数的地方最为有用。JAB的示例非常完美-最好与关键字参数一起使用key
,但它仍提供有用的信息。
什么时候
def key(x):
return x[1]
距离出现300行
[(1,2), (3,1), (5,10), (11,-3)].sort(key)
钥匙有什么作用?确实没有迹象。您可能会有某种猜测,尤其是如果您熟悉该功能时,但通常需要回头看看。太太
[(1,2), (3,1), (5,10), (11,-3)].sort(lambda x: x[1])
告诉你更多。
可能还有更多的信息,但是仅使用匿名lambda函数而不是命名函数,您已经获得了巨大的信息。
另外,它不会污染您的名称空间;)
key=
省略,则会引发TypeError )。我也忘记了sort
,它执行就地排序,实际上并没有返回它排序的对象,因此您必须在已经分配给变量的可变序列上使用它。
cmp
,不是key
)和python 3(其中sort
不接受任何位置参数)中都被破坏了。在这两种情况下,您都需要使用...sort(key=...)
。
是的,您是对的-这是结构性选择。仅使用lambda表达式可能不会使您的程序更正确。也没有使它们更可靠,这与速度无关。
这仅与灵活性和表达能力有关。喜欢列表理解。您可以完成大多数定义命名函数的操作(可能会污染名称空间,但这又纯粹是样式问题)。
它可以帮助您提高可读性,因为您不必定义单独的命名函数,其他人必须查找,阅读和理解它所做的只是在其参数上调用方法blah()。
当您使用它编写用于创建和返回其他函数的函数时,可能会更加有趣,这些函数的确切功能取决于其参数。这可能是一种非常简洁易读的参数化代码行为的方式。您可以表达更多有趣的想法。
但这仍然是结构性选择。否则,您可以这样做。但是面向对象编程也是如此;)
暂时忽略一下我们正在谈论的具体为匿名函数的细节。函数(包括匿名函数)在Python中是可分配的数量(几乎但不是真正的值)。像这样的表达
map(lambda y: y * -1, range(0, 10))
明确提到四个匿名数量:-1、0、10和lambda运算符的结果,以及map
调用的隐式结果。可以使用某些语言创建匿名类型的值。因此,请忽略函数和数字之间的表面区别。何时使用匿名函数而不是命名函数的问题类似于何时在代码中放置裸数字文字以及何时声明TIMES_I_WISHED_I_HAD_A_PONY
或的问题。BUFFER_SIZE
。有时适合使用(数字,字符串或函数)文字,有时更适合使用此类名称命名并通过其名称进行引用。
见。艾伦·霍鲁布(Allen Holub)关于Java设计模式的富有启发性,发人深省的书;他使用了很多匿名类。
Lambda虽然在某些情况下很有用,但很容易被滥用。lambda几乎总是使代码更难阅读。尽管将所有代码都放在一行中可能会让人满意,但它会吸引下一个必须阅读您的代码的人。
直接来自PEP8
“ Guido的主要见解之一是代码的读取次数比编写的次数要多。”
我已经学习过的lambda函数的一种用法,在哪里没有其他好的替代方法,或者至少在我看来是最好的,它是作为函数参数中的默认操作
parameter=lambda x: x
这将返回不变的值,但是您可以选择提供一个函数来执行转换或操作(例如打印答案,不仅返回)
通常,将排序用作键也很有用:
key=lambda x: x[field]
效果是按顺序对每个项目的fieldth(基于零的记忆)元素进行排序。对于反转,您不需要lambda,因为它更易于使用
reverse=True
通常,执行新的实函数并使用它代替lambda几乎一样容易。如果人们研究了很多Lisp或其他函数式编程,他们也自然会使用lambda函数,因为在Lisp中,函数定义是由lambda演算处理的。
Lambda是对象,而不是方法,并且不能以与方法相同的方式调用它们。例如
succ = ->(x){ x+1 }
succ mow包含一个Proc对象,我们可以像其他对象一样使用它:
succ.call(2)
给我们输出= 3
我想指出一种情况,除了列表处理之外,lambda函数似乎是最佳选择:
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函数,则该回调可能只执行一次回调。
ttk.Button(root, text = 'Button1', command = callback('Button1 clicked')).pack()
Lambda是匿名函数(无名称的函数),可以分配给变量,也可以作为参数传递给另一个函数。当您需要一小段功能可以同时运行一次或仅运行一次时,lambda就会有用。除了在全局范围内编写函数或将其包含在主程序中之外,您还可以在需要时将几行代码扔给变量或其他函数。同样,当您在函数调用期间将函数作为参数传递给另一个函数时,可以更改参数(匿名函数)以使函数本身具有动态性。假设匿名函数在其作用域之外使用变量,则称为闭包。这在回调函数中很有用。
在某些情况下,将简单的东西表示为lambda更为清晰。考虑常规排序与反向排序,例如:
some_list = [2, 1, 3]
print sorted(some_list)
print sorted(some_list, lambda a, b: -cmp(a, b))
对于后一种情况,编写单独的完整函数以返回a-cmp(a, b)
会比lambda产生更多的误解。
sorted(..., reverse=True)
sorted(..., lambda a,b: cmp(b,a))
确实,滥用lambda函数通常会导致错误且难以阅读的代码。另一方面,如果正确使用它,则相反。这个线程中已经有了不错的答案,但是我遇到的一个例子是:
def power(n):
return lambda x: x**n
square = power(2)
cubic = power(3)
quadruple = power(4)
print(square(10)) # 100
print(cubic(10)) # 1000
print(quadruple(10)) # 10000
无需使用lambda,可以通过许多其他方式重写此简化的案例。仍然可以通过此示例推断出lambda函数如何在可能更复杂的情况和函数中提高可读性和代码重用。
您掌握了lambda,您掌握了python中的快捷方式,这是为什么:
data=[(lambda x:x.text)(x.extract()) for x in soup.findAll('p') ]
^1 ^2 ^3 ^4
在这里,我们可以看到列表理解的4个部分:
我没有发现在lambda中使用2条语句的其他方法,但是通过这种管道内衬,我们可以利用lambda的无限潜力。
编辑:正如juanpa在评论中指出的那样,使用x.extract()。text完全可以,但是重点是解释了lambda管道的使用,即将lambda1的输出作为输入传递给lambda2。通过(lambda1 y:g(x))(lambda2 x:f(x))
x.extract().text
x.extract().text()
但重点是要解释“ lambda Pipe”。因为并非所有类都具有可以返回属性副本的方法。BS4可以选择这样做,但是通常不提供这种功能。
Lambda允许您即时创建函数。我见过的大多数示例除了创建具有在创建时传递的参数(而不是执行)的函数外,所做的工作不多。或者他们通过不需要在使用前正式声明功能来简化代码。
一个更有趣的用途是动态构造python函数,以评估直到运行时(用户输入)才知道的数学表达式。创建函数后,可以使用不同的参数重复调用该函数以评估表达式(例如您想绘制它)。给定eval(),这甚至可能是一个糟糕的例子。这种使用方式是“真正”力量的所在-动态创建更复杂的代码,而不是您经常看到的简单示例,这些示例只不过是减少(源)代码大小而已。