在Python中使用哪个更可取:lambda函数或者嵌套函数('def')?

时间:2020-03-06 14:44:04  来源:igfitidea点击:

我主要使用lambda函数,但有时使用似乎提供相同行为的嵌套函数。

这是一些琐碎的示例,如果在另一个函数中找到它们,它们在功能上会做同样的事情:

Lambda函数

>>> a = lambda x : 1 + x
>>> a(5)
6

嵌套功能

>>> def b(x): return 1 + x

>>> b(5)
6

使用一个相对于另一个有优势吗? (性能?可读性?局限性?一致性?等)

甚至有关系吗?如果不这样做,那确实违反了Pythonic原理:

“There should be one—and preferably only one—obvious way to do it”.

解决方案

如果我们需要将lambda分配给一个名称,请改用def。 def只是分配的语法糖,因此结果是相同的,并且它们更具灵活性和可读性。

lambda只能使用一次,丢弃没有名称的函数。

但是,这种用例非常少见。我们很少需要传递未命名的函数对象。

内置的map()和filter()需要函数对象,但是列表理解和生成器表达式通常比那些函数更具可读性,并且可以覆盖所有用例,而无需使用lambda。

在某些情况下,我们确实需要一个小的函数对象,应该使用operator模块功能,例如operator.add来代替lambda x,y:x + y。

如果仍然需要一些未涵盖的" lambda",则可以考虑编写一个" def",以提高可读性。如果功能比" operator"模块的功能复杂,则" def"可能更好。

因此,现实世界中好的" lambda"用例非常少见。

我同意nosklo的建议:如果我们需要给函数命名,请使用def。当我只是将简短的代码片段传递给另一个函数的情况下,我保留了lambda函数,例如:

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )

Guido van Rossum在这次采访中说,他希望自己不要让" lambda"进入Python:

"Q. What feature of Python are you least pleased with?

  Sometimes I've been too quick in accepting contributions, and later realized that it was a mistake. One example would be some of the functional programming features, such as lambda functions. lambda is a keyword that lets you create a small anonymous function; built-in functions such as map, filter, and reduce run a function over a sequence type, such as a list.

  In practice, it didn't turn out that well. Python only has two scopes: local and global. This makes writing lambda functions painful, because you often want to access variables in the scope where the lambda was defined, but you can't because of the two scopes. There's a way around this, but it's something of a kludge. Often it seems much easier in Python to just use a for loop instead of messing around with lambda functions. map and friends work well only when there's already a built-in function that does what you want.

恕我直言,Iambdas有时可能很方便,但是通常以可读性为代价很方便。你能告诉我这是怎么做的:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

我写了它,花了我一分钟才弄清楚。这是来自欧拉计画,我不会说哪个问题,因为我讨厌破坏者,但是它在0.124秒内运行:)

lambda的主要用途一直是用于简单的回调函数,以及用于map,reduce,filter,后者需要将函数用作参数。随着列表理解成为规范,并且允许添加,如:

x = [f for f in range(1, 40) if f % 2]

很难想象在日常使用中使用lambda的真实情况。因此,我要避免使用lambda并创建嵌套函数。

我同意nosklo。顺便说一句,即使使用一次,扔掉功能,大多数情况下,我们只想使用操作员模块中的某些功能。

例如:

我们有一个带有此签名的函数:myFunction(data,callback function)。

我们想传递一个添加2个元素的函数。

使用lambda:

myFunction(data, (lambda x, y : x + y))

pythonic方式:

import operator
myFunction(data, operator.add)

或者当然,这是一个简单的示例,但是操作员模块提供了很多东西,包括用于列表和字典的项目设置器/获取器。真的很酷。

实际上,对我来说有两个区别:

首先是关于他们的工作以及他们的回报:

  • def是不返回任何内容并在本地名称空间中创建"名称"的关键字。
  • lambda是一个返回函数对象的关键字,并且不会在本地名称空间中创建"名称"。

因此,如果我们需要调用带有函数对象的函数,则在一行python代码中执行此操作的唯一方法是使用lambda。 def没有等效功能。

在某些框架中,这实际上很常见。例如,我经常使用Twisted,

d.addCallback(lambda result: setattr(self, _someVariable, result))

是很常见的,并且对lambda更为简洁。

第二点区别是允许实际执行的功能。

  • 用'def'定义的函数可以包含任何python代码
  • 用" lambda"定义的函数必须求值为表达式,因此不能包含诸如print,import,raise,...之类的语句。

例如,

def p(x): print x

按预期工作,而

lambda x: print x

是一个SyntaxError。

当然,有些解决方法是将print替换为sys.stdout.write,或者将import替换为__import__。但是通常情况下,最好还是使用一个函数。

如果仅要将lambda分配给本地范围内的变量,则最好使用def,因为它更具可读性,并且将来可以更轻松地扩展:

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

或者

def fun(a, b): return a ** b # more readable
map(fun, someList)

lambda对于生成新函数很有用:

def somefunc(x): return lambda y: x+y
f = somefunc(10)
f(2)
>>> 12
f(4)
>>> 14

Lambda的一个重要限制是它们除了表达式外不能包含其他任何内容。 lambda表达式几乎不可能产生任何琐碎的副作用,因为它不能像" def"函数那样具有丰富的身体。

话虽这么说,Lua影响了我的编程风格,使之广泛地使用了匿名函数,所以我在其中随便乱扔了代码。最重要的是,我倾向于将map / reduce视为抽象运算符,而不考虑列表推导或者生成器,就好像我要通过使用这些运算符明确推迟实现决策一样。

编辑:这是一个很老的问题,我对此事的看法有所改变。

首先,我强烈反对为变量分配lambda表达式。因为python为此具有特殊的语法(提示,def)。除此之外,lambda的许多用途(即使没有名称)都具有预定义的(并且效率更高)的实现。例如,所讨论的示例可以缩写为(1).__ add__,而无需将其包装在lambda或者def中。使用operator,itertools和functools模块的某种组合可以满足许多其他常见用途。