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

时间:2022-06-10 10:24:46

I mostly use lambda functions but sometimes use nested functions that seem to provide the same behavior.

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

Here are some trivial examples where they functionally do the same thing if either were found within another function:

这里有一些简单的例子,它们在功能上做同样的事情,如果它们在另一个函数中被发现:

Lambda function

Lambda函数

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

Nested function

嵌套函数

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

>>> b(5)
6

Are there advantages to using one over the other? (Performance? Readability? Limitations? Consistency? etc.)

用一个比另一个好吗?(性能?可读性呢?限制吗?一致性?等等)。

Does it even matter? If it doesn't then does that violate the Pythonic principle:

它甚至有关系吗?如果它没有违背python法则

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

“应该有一种——最好是唯一一种显而易见的方法”。

15 个解决方案

#1


83  

If you need to assign the lambda to a name, use a def instead. defs are just syntactic sugar for an assignment, so the result is the same, and they are a lot more flexible and readable.

如果需要将lambda分配给一个名称,则使用def代替。defs只是一个任务的语法糖,所以结果是一样的,而且它们更加灵活和可读。

lambdas can be used for use once, throw away functions which won't have a name.

lambdas可以被使用一次,丢掉那些没有名字的函数。

However, this use case is very rare. You rarely need to pass around unnamed function objects.

然而,这个用例非常罕见。您很少需要传递未命名的函数对象。

The builtins map() and filter() need function objects, but list comprehensions and generator expressions are generally more readable than those functions and can cover all use cases, without the need of lambdas.

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

For the cases you really need a small function object, you should use the operator module functions, like operator.add instead of lambda x, y: x + y

对于实际需要一个小函数对象的情况,应该使用操作符模块函数,比如操作符。加上x y: x + y。

If you still need some lambda not covered, you might consider writing a def, just to be more readable. If the function is more complex than the ones at operator module, a def is probably better.

如果您仍然需要一些未覆盖的lambda,您可以考虑编写一个def,以使其可读性更好。如果函数比操作符模块中的函数更复杂,那么def可能更好。

So, real world good lambda use cases are very rare.

所以,真实世界好的lambda用例非常罕见。

#2


25  

Practically speaking, to me there are two differences:

实际上,对我来说有两种不同:

The first is about what they do and what they return:

第一个是关于他们所做的和他们的回报:

  • def is a keyword that doesn't return anything and creates a 'name' in the local namespace.

    def是一个不返回任何东西并在本地名称空间中创建“名称”的关键字。

  • lambda is a keyword that returns a function object and does not create a 'name' in the local namespace.

    lambda是返回一个函数对象的关键字,它不会在本地名称空间中创建“名称”。

Hence, if you need to call a function that takes a function object, the only way to do that in one line of python code is with a lambda. There's no equivalent with def.

因此,如果您需要调用一个函数来获取函数对象,那么在python代码的一行代码中唯一的方法就是使用lambda。def是不一样的。

In some frameworks this is actually quite common; for example, I use Twisted a lot, and so doing something like

在一些框架中,这是很常见的;例如,我经常使用Twisted,所以做一些类似的事情。

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

is quite common, and more concise with lambdas.

这是很常见的,并且更简洁的lambdas。

The second difference is about what the actual function is allowed to do.

第二个区别是实际的函数允许做什么。

  • A function defined with 'def' can contain any python code
  • 定义为“def”的函数可以包含任何python代码。
  • A function defined with 'lambda' has to evaluate to an expression, and can thus not contain statements like print, import, raise, ...
  • 用“lambda”定义的函数必须对表达式求值,因此不能包含像print、import、raise、……

For example,

例如,

def p(x): print x

works as expected, while

像预期的那样工作,

lambda x: print x

is a SyntaxError.

是一个SyntaxError。

Of course, there are workarounds - substitute print with sys.stdout.write, or import with __import__. But usually you're better off going with a function in that case.

当然,也有变通方法——用sys.stdout代替打印。用__import__书写或导入。但通常情况下,你最好使用函数。

#3


16  

In this interview, Guido van Rossum says he wishes he hadn't let 'lambda' into Python:

在这次采访中,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.

问:你最不喜欢Python的什么特性?有时我太急于接受别人的贡献,后来才意识到这是个错误。一个例子是一些函数式编程特性,比如lambda函数。lambda是一个关键字,可以让您创建一个小的匿名函数;内置的函数,例如map、filter和reduce,可以在序列类型上运行一个函数,比如列表。实际上,结果并不是那么好。Python只有两个作用域:本地和全局。这使得编写lambda函数非常痛苦,因为您通常希望在定义lambda的范围内访问变量,但是您不能因为两个作用域。有一种方法,但它是一种拼凑物。在Python中,使用for循环而不是使用lambda函数似乎更容易。只有当有一个内置的函数可以做你想做的事情时,地图和朋友才能工作得很好。

IMHO, Iambdas can be convenient sometimes, but usually are convenient at the expense of readibility. Can you tell me what this does:

IMHO, Iambdas有时候是很方便的,但是通常都是方便的,而不是容易的。你能告诉我这是干什么的吗?

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

I wrote it, and it took me a minute to figure it out. This is from Project Euler - i won't say which problem because i hate spoilers, but it runs in 0.124 seconds :)

我写了,我花了一分钟才弄明白。这来自Project Euler——我不会说哪个问题,因为我讨厌剧透,但它的运行时间是0.124秒:)

#4


9  

For n=1000 here's some timeit's of calling a function vs a lambda:

对于n=1000,这里有一段时间它是调用函数vs。

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

#5


6  

I agree with nosklo's advice: if you need to give the function a name, use def. I reserve lambda functions for cases where I'm just passing a brief snippet of code to another function, e.g.:

我同意nosklo的建议:如果您需要给函数一个名称,请使用def.我保留lambda函数,以便将一个简短的代码片段传递给另一个函数,例如:

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

#6


5  

Performance:

性能:

Creating a function with lambda is slightly faster than creating it with def. The difference is due to def creating a name entry in the locals table. The resulting function has the same execution speed.

用lambda创建一个函数比用def创建函数要稍微快一些,这是因为def在本地表中创建了一个名称条目。得到的函数具有相同的执行速度。


Readability:

可读性:

Lambda functions are somewhat less readable for most Python users, but also much more concise in some circumstances. Consider converting from using non-functional to functional routine:

对于大多数Python用户来说,Lambda函数的可读性有点低,但在某些情况下也更简洁。考虑将非功能性转换为功能例程:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

As you can see, the lambda version is shorter and "easier" in the sense that you only need to add lambda v: to the original non-functional version to convert to the functional version. It's also a lot more concise. But remember, a lot of Python users will be confused by the lambda syntax, so what you lose in length and real complexity might be gained back in confusion from fellow coders.

正如您所看到的,lambda版本较短,而且“更容易”,因为您只需要添加lambda v:到原始的非功能版本,以转换为功能版本。它也更简洁。但是请记住,许多Python用户将会被lambda语法所迷惑,因此您在长度和实际复杂性上的损失可能会从其他程序员的混乱中得到。


Limitations:

限制:

  • lambda functions can only be used once, unless assigned to a variable name.
  • lambda函数只能使用一次,除非分配给变量名。
  • lambda functions assigned to variable names have no advantage over def functions.
  • 被分配给变量名的函数与def函数没有任何优势。
  • lambda functions can be difficult or impossible to pickle.
  • lambda函数可能很难或不可能被pickle。
  • def functions' names must be carefully chosen to be reasonably descriptive and unique or at least otherwise unused in scope.
  • 定义函数的名称必须谨慎地选择,以便合理地描述和独特,或者至少在其他方面没有使用。

Consistency:

一致性:

Python mostly avoids functional programming conventions in favor of procedural and simpler objective semantics. The lambda operator stands in direct contrast to this bias. Moreover, as an alternative to the already prevalent def, the lambda function adds diversity to your syntax. Some would consider that less consistent.

Python基本上避免了函数式编程约定,而支持过程化和更简单的客观语义。lambda运算符与这种偏差形成了直接对比。此外,作为已经流行的def的替代,lambda函数为您的语法增加了多样性。一些人会认为这是不一致的。


Pre-existing functions:

已有的功能:

As noted by others, many uses of lambda in the field can be replaced by members of the operator or other modules. For instance:

正如其他人所指出的,在字段中使用lambda的许多用法可以由操作符或其他模块的成员替换。例如:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

Using the pre-existing function can make code more readable in many cases.

使用预先存在的函数可以使代码在许多情况下更具可读性。


The Pythonic principle: “There should be one—and preferably only one—obvious way to do it”

python的原理是:“应该有一种——最好是唯一一种显而易见的方法”

That's similar to the single source of truth doctrine. Unfortunately, the single-obvious-way-to-do-it principle has always been more an wistful aspiration for Python, rather than a true guiding principal. Consider the very-powerful array comprehensions in Python. They are functionally equivalent to the map and filter functions:

这类似于真理教条的单一来源。不幸的是,这一简单而又可行的原则一直以来都是对Python的渴望,而不是真正的指导原则。考虑Python中非常强大的数组理解。它们在功能上等同于map和filter函数:

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambda and def are the same.

和def是一样的。

It's a matter of opinion, but I would say that anything in the Python language intended for general use which doesn't obviously break anything is "Pythonic" enough.

这是一个观点问题,但我要说的是,在Python语言中,任何用于一般用途的东西都没有明显的突破,那就是“Python化”。

#7


4  

The primary use of lambda has always been for simple callback functions, and for map, reduce, filter, which require a function as an argument. With list comprehensions becoming the norm, and the added allowed if as in:

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

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

it's hard to imagine a real case for the use of lambda in daily use. As a result, I'd say, avoid lambda and create nested functions.

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

#8


3  

An important limitation of lambdas is that they cannot contain anything besides an expression. It's nearly impossible for a lambda expression to produce anything besides trivial side effects, since it cannot have anywhere near as rich a body as a def'ed function.

lambdas的一个重要限制是,除了表达式之外,它们不能包含任何内容。一个lambda表达式几乎不可能产生除了简单的副作用之外的任何东西,因为它不能像def的函数那样有足够的功能。

That being said, Lua influenced my programming style toward the extensive use of anonymous functions, and I litter my code with them. On top of that, I tend to think about map/reduce as abstract operators in ways I don't consider list comprehensions or generators, almost as If I'm deferring an implementation decision explicitly by using those operators.

也就是说,Lua影响了我对匿名函数的广泛使用的编程风格,我将代码与它们混在一起。最重要的是,我倾向于将map/reduce作为抽象的操作符,而不考虑列表的理解和生成器,就好像我是通过使用这些操作符来显式地推迟实现决策。

Edit: This is a pretty old question, and my opinions on the matter have changed, somewhat.

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

First off, I am strongly biased against assigning a lambda expression to a variable; as python has a special syntax just for that (hint, def). In addition to that, many of the uses for lambda, even when they don't get a name, have predefined (and more efficient) implementations. For instance, the example in question can be abbreviated to just (1).__add__, without the need to wrap it in a lambda or def. Many other common uses can be satisfied with some combination of the operator, itertools and functools modules.

首先,我强烈反对将lambda表达式赋值给变量;因为python有一种特殊的语法(提示,def)。除此之外,lambda的许多用途,即使它们没有名称,也有预定义的(和更有效的)实现。例如,问题中的示例可以缩写为just (1).__add__,而不需要将其封装在lambda或def中。许多其他常见的用法可以通过操作符、itertools和functools模块的组合来满足。

#9


3  

While agreeing with the other answers, sometimes it's more readable. Here's an example where lambda comes in handy, in a use case I keep encountering of an N dimensional defaultdict.
Here's an example:

虽然同意其他的答案,但有时可读性更好。这里有一个例子,在一个用例中,我一直遇到一个N维的defaultdict。这里有一个例子:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

I find it more readable than creating a def for the second dimension. This is even more significant for higher dimensions.

我发现它比为第二个维度创建def更具可读性。这对于更高维度更重要。

#10


2  

One use for lambdas I have found... is in debug messages.

我发现了一个对lambdas的使用…在调试消息。

Since lambdas can be lazily evaluated you can have code like this:

由于lambdas可以被延迟评估,您可以有如下代码:

log.debug(lambda: "this is my message: %r" % (some_data,))

instead of possibly expensive:

相反可能昂贵的:

log.debug("this is my message: %r" % (some_data,))

which processes the format string even if the debug call does not produce output because of current logging level.

即使调试调用由于当前日志级别而不产生输出,也会处理格式字符串。

Of course for it to work as described the logging module in use must support lambdas as "lazy parameters" (as my logging module does).

当然,正如所描述的,使用日志模块必须支持lambdas作为“惰性参数”(正如我的日志模块所做的那样)。

The same idea may be applied to any other case of lazy evaluation for on demand content value creation.

同样的想法可能适用于任何其他的关于需求内容价值创造的懒惰评估的例子。

For example this custom ternary operator:

例如,这个自定义三元操作符:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

instead of:

而不是:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

with lambdas only the expression selected by the condition will be evaluated, without lambdas both will be evaluated.

对于lambdas,仅对条件选中的表达式进行评估,而不使用lambdas,将对它们进行评估。

Of course you could simply use functions instead of lambdas, but for short expressions lambdas are (c)leaner.

当然,您可以简单地使用函数而不是lambdas,但是对于简短的表达式,lambdas是(c)leaner。

#11


2  

More preferable: lambda functions or nested functions (def)?

There is one advantage to using a lambda over a regular function (they are created in an expression), and several drawbacks. For that reason, I prefer to create functions with the def keyword instead of with lambdas.

使用lambda /正则函数(它们是在表达式中创建的)有一个优点,也有一些缺点。出于这个原因,我更喜欢用def关键字来创建函数,而不是使用lambdas。

First point - they're the same type of object

A lambda results in the same type of object as a regular function

lambda结果与常规函数相同类型的对象。

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

Since lambdas are functions, they're first-class objects.

因为lambdas是函数,所以它们是一级对象。

Both lambdas and functions:

λ和功能:

  • can be passed around as an argument (same as a regular function)
  • 可以作为参数传递(与常规函数相同)
  • when created within an outer function become a closure over that outer functions' locals
  • 当在外部函数中创建时,就会关闭外部函数的本地函数。

But lambdas are, by default, missing some things that functions get via full function definition syntax.

但是,在默认情况下,lambdas忽略了一些函数通过完整的函数定义语法获得的功能。

A lamba's __name__ is '<lambda>'

Lambdas are anonymous functions, after all, so they don't know their own name.

Lambdas是匿名函数,所以他们不知道自己的名字。

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

Thus lambda's can't be looked up programmatically in their namespace.

因此,不能在它们的名称空间中以编程方式查找lambda。

This limits certain things. For example, foo can be looked up with serialized code, while l cannot:

这限制了某些事情。例如,可以使用序列化代码查找foo,而l不能:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

We can lookup foo just fine - because it knows its own name:

我们可以查找foo,因为它知道自己的名字:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

Lambdas have no annotations and no docstring

Basically, lambdas are not documented. Let's rewrite foo to be better documented:

基本上,lambdas没有文档化。让我们重写一下foo,以便更好地记录:

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

Now, foo has documentation:

现在,foo文档:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

Whereas, we don't have the same mechanism to give the same information to lambdas:

然而,我们没有相同的机制来给lambdas提供相同的信息:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

But we can hack them on:

但是我们可以攻击他们:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

But there's probably some error messing up the output of help, though.

但是,可能会有一些错误把帮助的输出搞得一团糟。

Lambdas can only return an expression

Lambdas can't return complex statements, only expressions.

Lambdas不能返回复杂的语句,只能返回表达式。

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

Expressions can admittedly be rather complex, and if you try very hard you can probably accomplish the same with a lambda, but the added complexity is more of a detriment to writing clear code.

诚然,表达式是相当复杂的,如果您非常努力,您可能会用lambda实现相同的表达式,但是增加的复杂性会对编写清晰的代码造成更大的损害。

We use Python for clarity and maintainability. Overuse of lambdas can work against that.

为了清晰和可维护性,我们使用Python。过度使用lambdas可以解决这个问题。

The only upside for lambdas: can be created in a single expression

This is the only possible upside. Since you can create a lambda with an expression, you can create it inside of a function call.

这是唯一可能的好处。因为您可以使用表达式创建lambda,您可以在函数调用内部创建它。

Creating a function inside a function call avoids the (inexpensive) name lookup versus one created elsewhere.

在函数调用中创建函数可以避免(便宜的)名称查找,而不是在其他地方创建。

However, since Python is strictly evaluated, there is no other performance gain to doing so aside from avoiding the name lookup.

然而,由于严格地评估了Python,所以除了避免名称查找之外,没有其他性能提升。

For a very simple expression, I might choose a lambda.

对于一个非常简单的表达式,我可以选择一个。

I also tend to use lambdas when doing interactive Python, to avoid multiple lines when one will do. I use the following sort of code format when I want to pass in an argument to a constructor when calling timeit.repeat:

在使用交互式Python时,我也倾向于使用lambdas,以避免在使用时使用多行。当我想在调用时间时将参数传递给构造函数时,我使用以下代码格式。

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

And now:

现在:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

I believe the slight time difference above can be attributed to the name lookup in return_nullary_function - note that it is very negligible.

我认为上面的细微时间差可以归因于return_nullary_function中的名称查找——注意它是非常微不足道的。

Conclusion

Lambdas are good for informal situations where you want to minimize lines of code in favor of making a singular point.

Lambdas适用于您希望最小化代码行,以创建一个奇异点的非正式场合。

Lambdas are bad for more formal situations where you need clarity for editors of code who will come later, especially in cases where they are non-trivial.

Lambdas对于更正式的情况是不好的,在这种情况下,您需要对稍后会出现的代码编辑器进行清晰的处理,特别是在它们是非平凡的情况下。

We know we are supposed to give our objects good names. How can we do so when the object has no name?

我们知道我们应该给我们的对象起好名字。当对象没有名称时,我们怎么做呢?

For all of these reasons, I prefer to create functions with def instead of with lambda.

出于所有这些原因,我倾向于用def而不是lambda来创建函数。

#12


0  

I agree with nosklo. By the way, even with a use once, throw away function, most of the time you just want to use something from the operator module.

我同意nosklo。顺便说一下,即使有一次使用,扔掉函数,大多数时候你只是想从操作模块中使用一些东西。

E.G :

E。旅客:

You have a function with this signature : myFunction(data, callback function).

您有一个具有此签名的函数:myFunction(数据、回调函数)。

You want to pass a function that add 2 elements.

要传递一个添加两个元素的函数。

Using lambda :

使用λ:

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

The pythonic way :

神谕的道:

import operator
myFunction(data, operator.add)

Or course this is a simple example, but there is a lot of stuff the operator module provides, including the items setters / getters for list and dict. Really cool.

或者这是一个简单的例子,但是操作员模块提供了很多东西,包括列表和命令的setter / getter。

#13


0  

If you are just going to assign the lambda to a variable in the local scope, you may as well use def because it is more readable and can be expanded more easily in the future:

如果您只是将lambda分配给局部范围内的变量,那么您可以使用def,因为它更具可读性,并且在将来可以更容易地扩展:

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

or

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

#14


-1  

lambda is usefull for generating new functions:

用于生成新的函数:

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

#15


-1  

A major difference is that you can not use def functions inline, which is in my opinion the most convenient use case for a lambda function. For example when sorting a list of objects:

一个主要的区别是,您不能在内联中使用def函数,这在我看来是lambda函数最方便的用例。例如,在排序对象列表时:

my_list.sort(key=lambda o: o.x)

I would therefore suggest keeping the use of lambdas to this kind of trivial operations, which also do not really benefit from the automatic documentation provided by naming the function.

因此,我建议将lambdas的使用保留到这种琐碎的操作中,这也不会从命名函数所提供的自动文档中获益。

#1


83  

If you need to assign the lambda to a name, use a def instead. defs are just syntactic sugar for an assignment, so the result is the same, and they are a lot more flexible and readable.

如果需要将lambda分配给一个名称,则使用def代替。defs只是一个任务的语法糖,所以结果是一样的,而且它们更加灵活和可读。

lambdas can be used for use once, throw away functions which won't have a name.

lambdas可以被使用一次,丢掉那些没有名字的函数。

However, this use case is very rare. You rarely need to pass around unnamed function objects.

然而,这个用例非常罕见。您很少需要传递未命名的函数对象。

The builtins map() and filter() need function objects, but list comprehensions and generator expressions are generally more readable than those functions and can cover all use cases, without the need of lambdas.

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

For the cases you really need a small function object, you should use the operator module functions, like operator.add instead of lambda x, y: x + y

对于实际需要一个小函数对象的情况,应该使用操作符模块函数,比如操作符。加上x y: x + y。

If you still need some lambda not covered, you might consider writing a def, just to be more readable. If the function is more complex than the ones at operator module, a def is probably better.

如果您仍然需要一些未覆盖的lambda,您可以考虑编写一个def,以使其可读性更好。如果函数比操作符模块中的函数更复杂,那么def可能更好。

So, real world good lambda use cases are very rare.

所以,真实世界好的lambda用例非常罕见。

#2


25  

Practically speaking, to me there are two differences:

实际上,对我来说有两种不同:

The first is about what they do and what they return:

第一个是关于他们所做的和他们的回报:

  • def is a keyword that doesn't return anything and creates a 'name' in the local namespace.

    def是一个不返回任何东西并在本地名称空间中创建“名称”的关键字。

  • lambda is a keyword that returns a function object and does not create a 'name' in the local namespace.

    lambda是返回一个函数对象的关键字,它不会在本地名称空间中创建“名称”。

Hence, if you need to call a function that takes a function object, the only way to do that in one line of python code is with a lambda. There's no equivalent with def.

因此,如果您需要调用一个函数来获取函数对象,那么在python代码的一行代码中唯一的方法就是使用lambda。def是不一样的。

In some frameworks this is actually quite common; for example, I use Twisted a lot, and so doing something like

在一些框架中,这是很常见的;例如,我经常使用Twisted,所以做一些类似的事情。

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

is quite common, and more concise with lambdas.

这是很常见的,并且更简洁的lambdas。

The second difference is about what the actual function is allowed to do.

第二个区别是实际的函数允许做什么。

  • A function defined with 'def' can contain any python code
  • 定义为“def”的函数可以包含任何python代码。
  • A function defined with 'lambda' has to evaluate to an expression, and can thus not contain statements like print, import, raise, ...
  • 用“lambda”定义的函数必须对表达式求值,因此不能包含像print、import、raise、……

For example,

例如,

def p(x): print x

works as expected, while

像预期的那样工作,

lambda x: print x

is a SyntaxError.

是一个SyntaxError。

Of course, there are workarounds - substitute print with sys.stdout.write, or import with __import__. But usually you're better off going with a function in that case.

当然,也有变通方法——用sys.stdout代替打印。用__import__书写或导入。但通常情况下,你最好使用函数。

#3


16  

In this interview, Guido van Rossum says he wishes he hadn't let 'lambda' into Python:

在这次采访中,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.

问:你最不喜欢Python的什么特性?有时我太急于接受别人的贡献,后来才意识到这是个错误。一个例子是一些函数式编程特性,比如lambda函数。lambda是一个关键字,可以让您创建一个小的匿名函数;内置的函数,例如map、filter和reduce,可以在序列类型上运行一个函数,比如列表。实际上,结果并不是那么好。Python只有两个作用域:本地和全局。这使得编写lambda函数非常痛苦,因为您通常希望在定义lambda的范围内访问变量,但是您不能因为两个作用域。有一种方法,但它是一种拼凑物。在Python中,使用for循环而不是使用lambda函数似乎更容易。只有当有一个内置的函数可以做你想做的事情时,地图和朋友才能工作得很好。

IMHO, Iambdas can be convenient sometimes, but usually are convenient at the expense of readibility. Can you tell me what this does:

IMHO, Iambdas有时候是很方便的,但是通常都是方便的,而不是容易的。你能告诉我这是干什么的吗?

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

I wrote it, and it took me a minute to figure it out. This is from Project Euler - i won't say which problem because i hate spoilers, but it runs in 0.124 seconds :)

我写了,我花了一分钟才弄明白。这来自Project Euler——我不会说哪个问题,因为我讨厌剧透,但它的运行时间是0.124秒:)

#4


9  

For n=1000 here's some timeit's of calling a function vs a lambda:

对于n=1000,这里有一段时间它是调用函数vs。

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

#5


6  

I agree with nosklo's advice: if you need to give the function a name, use def. I reserve lambda functions for cases where I'm just passing a brief snippet of code to another function, e.g.:

我同意nosklo的建议:如果您需要给函数一个名称,请使用def.我保留lambda函数,以便将一个简短的代码片段传递给另一个函数,例如:

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

#6


5  

Performance:

性能:

Creating a function with lambda is slightly faster than creating it with def. The difference is due to def creating a name entry in the locals table. The resulting function has the same execution speed.

用lambda创建一个函数比用def创建函数要稍微快一些,这是因为def在本地表中创建了一个名称条目。得到的函数具有相同的执行速度。


Readability:

可读性:

Lambda functions are somewhat less readable for most Python users, but also much more concise in some circumstances. Consider converting from using non-functional to functional routine:

对于大多数Python用户来说,Lambda函数的可读性有点低,但在某些情况下也更简洁。考虑将非功能性转换为功能例程:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

As you can see, the lambda version is shorter and "easier" in the sense that you only need to add lambda v: to the original non-functional version to convert to the functional version. It's also a lot more concise. But remember, a lot of Python users will be confused by the lambda syntax, so what you lose in length and real complexity might be gained back in confusion from fellow coders.

正如您所看到的,lambda版本较短,而且“更容易”,因为您只需要添加lambda v:到原始的非功能版本,以转换为功能版本。它也更简洁。但是请记住,许多Python用户将会被lambda语法所迷惑,因此您在长度和实际复杂性上的损失可能会从其他程序员的混乱中得到。


Limitations:

限制:

  • lambda functions can only be used once, unless assigned to a variable name.
  • lambda函数只能使用一次,除非分配给变量名。
  • lambda functions assigned to variable names have no advantage over def functions.
  • 被分配给变量名的函数与def函数没有任何优势。
  • lambda functions can be difficult or impossible to pickle.
  • lambda函数可能很难或不可能被pickle。
  • def functions' names must be carefully chosen to be reasonably descriptive and unique or at least otherwise unused in scope.
  • 定义函数的名称必须谨慎地选择,以便合理地描述和独特,或者至少在其他方面没有使用。

Consistency:

一致性:

Python mostly avoids functional programming conventions in favor of procedural and simpler objective semantics. The lambda operator stands in direct contrast to this bias. Moreover, as an alternative to the already prevalent def, the lambda function adds diversity to your syntax. Some would consider that less consistent.

Python基本上避免了函数式编程约定,而支持过程化和更简单的客观语义。lambda运算符与这种偏差形成了直接对比。此外,作为已经流行的def的替代,lambda函数为您的语法增加了多样性。一些人会认为这是不一致的。


Pre-existing functions:

已有的功能:

As noted by others, many uses of lambda in the field can be replaced by members of the operator or other modules. For instance:

正如其他人所指出的,在字段中使用lambda的许多用法可以由操作符或其他模块的成员替换。例如:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

Using the pre-existing function can make code more readable in many cases.

使用预先存在的函数可以使代码在许多情况下更具可读性。


The Pythonic principle: “There should be one—and preferably only one—obvious way to do it”

python的原理是:“应该有一种——最好是唯一一种显而易见的方法”

That's similar to the single source of truth doctrine. Unfortunately, the single-obvious-way-to-do-it principle has always been more an wistful aspiration for Python, rather than a true guiding principal. Consider the very-powerful array comprehensions in Python. They are functionally equivalent to the map and filter functions:

这类似于真理教条的单一来源。不幸的是,这一简单而又可行的原则一直以来都是对Python的渴望,而不是真正的指导原则。考虑Python中非常强大的数组理解。它们在功能上等同于map和filter函数:

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambda and def are the same.

和def是一样的。

It's a matter of opinion, but I would say that anything in the Python language intended for general use which doesn't obviously break anything is "Pythonic" enough.

这是一个观点问题,但我要说的是,在Python语言中,任何用于一般用途的东西都没有明显的突破,那就是“Python化”。

#7


4  

The primary use of lambda has always been for simple callback functions, and for map, reduce, filter, which require a function as an argument. With list comprehensions becoming the norm, and the added allowed if as in:

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

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

it's hard to imagine a real case for the use of lambda in daily use. As a result, I'd say, avoid lambda and create nested functions.

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

#8


3  

An important limitation of lambdas is that they cannot contain anything besides an expression. It's nearly impossible for a lambda expression to produce anything besides trivial side effects, since it cannot have anywhere near as rich a body as a def'ed function.

lambdas的一个重要限制是,除了表达式之外,它们不能包含任何内容。一个lambda表达式几乎不可能产生除了简单的副作用之外的任何东西,因为它不能像def的函数那样有足够的功能。

That being said, Lua influenced my programming style toward the extensive use of anonymous functions, and I litter my code with them. On top of that, I tend to think about map/reduce as abstract operators in ways I don't consider list comprehensions or generators, almost as If I'm deferring an implementation decision explicitly by using those operators.

也就是说,Lua影响了我对匿名函数的广泛使用的编程风格,我将代码与它们混在一起。最重要的是,我倾向于将map/reduce作为抽象的操作符,而不考虑列表的理解和生成器,就好像我是通过使用这些操作符来显式地推迟实现决策。

Edit: This is a pretty old question, and my opinions on the matter have changed, somewhat.

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

First off, I am strongly biased against assigning a lambda expression to a variable; as python has a special syntax just for that (hint, def). In addition to that, many of the uses for lambda, even when they don't get a name, have predefined (and more efficient) implementations. For instance, the example in question can be abbreviated to just (1).__add__, without the need to wrap it in a lambda or def. Many other common uses can be satisfied with some combination of the operator, itertools and functools modules.

首先,我强烈反对将lambda表达式赋值给变量;因为python有一种特殊的语法(提示,def)。除此之外,lambda的许多用途,即使它们没有名称,也有预定义的(和更有效的)实现。例如,问题中的示例可以缩写为just (1).__add__,而不需要将其封装在lambda或def中。许多其他常见的用法可以通过操作符、itertools和functools模块的组合来满足。

#9


3  

While agreeing with the other answers, sometimes it's more readable. Here's an example where lambda comes in handy, in a use case I keep encountering of an N dimensional defaultdict.
Here's an example:

虽然同意其他的答案,但有时可读性更好。这里有一个例子,在一个用例中,我一直遇到一个N维的defaultdict。这里有一个例子:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

I find it more readable than creating a def for the second dimension. This is even more significant for higher dimensions.

我发现它比为第二个维度创建def更具可读性。这对于更高维度更重要。

#10


2  

One use for lambdas I have found... is in debug messages.

我发现了一个对lambdas的使用…在调试消息。

Since lambdas can be lazily evaluated you can have code like this:

由于lambdas可以被延迟评估,您可以有如下代码:

log.debug(lambda: "this is my message: %r" % (some_data,))

instead of possibly expensive:

相反可能昂贵的:

log.debug("this is my message: %r" % (some_data,))

which processes the format string even if the debug call does not produce output because of current logging level.

即使调试调用由于当前日志级别而不产生输出,也会处理格式字符串。

Of course for it to work as described the logging module in use must support lambdas as "lazy parameters" (as my logging module does).

当然,正如所描述的,使用日志模块必须支持lambdas作为“惰性参数”(正如我的日志模块所做的那样)。

The same idea may be applied to any other case of lazy evaluation for on demand content value creation.

同样的想法可能适用于任何其他的关于需求内容价值创造的懒惰评估的例子。

For example this custom ternary operator:

例如,这个自定义三元操作符:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

instead of:

而不是:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

with lambdas only the expression selected by the condition will be evaluated, without lambdas both will be evaluated.

对于lambdas,仅对条件选中的表达式进行评估,而不使用lambdas,将对它们进行评估。

Of course you could simply use functions instead of lambdas, but for short expressions lambdas are (c)leaner.

当然,您可以简单地使用函数而不是lambdas,但是对于简短的表达式,lambdas是(c)leaner。

#11


2  

More preferable: lambda functions or nested functions (def)?

There is one advantage to using a lambda over a regular function (they are created in an expression), and several drawbacks. For that reason, I prefer to create functions with the def keyword instead of with lambdas.

使用lambda /正则函数(它们是在表达式中创建的)有一个优点,也有一些缺点。出于这个原因,我更喜欢用def关键字来创建函数,而不是使用lambdas。

First point - they're the same type of object

A lambda results in the same type of object as a regular function

lambda结果与常规函数相同类型的对象。

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

Since lambdas are functions, they're first-class objects.

因为lambdas是函数,所以它们是一级对象。

Both lambdas and functions:

λ和功能:

  • can be passed around as an argument (same as a regular function)
  • 可以作为参数传递(与常规函数相同)
  • when created within an outer function become a closure over that outer functions' locals
  • 当在外部函数中创建时,就会关闭外部函数的本地函数。

But lambdas are, by default, missing some things that functions get via full function definition syntax.

但是,在默认情况下,lambdas忽略了一些函数通过完整的函数定义语法获得的功能。

A lamba's __name__ is '<lambda>'

Lambdas are anonymous functions, after all, so they don't know their own name.

Lambdas是匿名函数,所以他们不知道自己的名字。

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

Thus lambda's can't be looked up programmatically in their namespace.

因此,不能在它们的名称空间中以编程方式查找lambda。

This limits certain things. For example, foo can be looked up with serialized code, while l cannot:

这限制了某些事情。例如,可以使用序列化代码查找foo,而l不能:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

We can lookup foo just fine - because it knows its own name:

我们可以查找foo,因为它知道自己的名字:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

Lambdas have no annotations and no docstring

Basically, lambdas are not documented. Let's rewrite foo to be better documented:

基本上,lambdas没有文档化。让我们重写一下foo,以便更好地记录:

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

Now, foo has documentation:

现在,foo文档:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

Whereas, we don't have the same mechanism to give the same information to lambdas:

然而,我们没有相同的机制来给lambdas提供相同的信息:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

But we can hack them on:

但是我们可以攻击他们:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

But there's probably some error messing up the output of help, though.

但是,可能会有一些错误把帮助的输出搞得一团糟。

Lambdas can only return an expression

Lambdas can't return complex statements, only expressions.

Lambdas不能返回复杂的语句,只能返回表达式。

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

Expressions can admittedly be rather complex, and if you try very hard you can probably accomplish the same with a lambda, but the added complexity is more of a detriment to writing clear code.

诚然,表达式是相当复杂的,如果您非常努力,您可能会用lambda实现相同的表达式,但是增加的复杂性会对编写清晰的代码造成更大的损害。

We use Python for clarity and maintainability. Overuse of lambdas can work against that.

为了清晰和可维护性,我们使用Python。过度使用lambdas可以解决这个问题。

The only upside for lambdas: can be created in a single expression

This is the only possible upside. Since you can create a lambda with an expression, you can create it inside of a function call.

这是唯一可能的好处。因为您可以使用表达式创建lambda,您可以在函数调用内部创建它。

Creating a function inside a function call avoids the (inexpensive) name lookup versus one created elsewhere.

在函数调用中创建函数可以避免(便宜的)名称查找,而不是在其他地方创建。

However, since Python is strictly evaluated, there is no other performance gain to doing so aside from avoiding the name lookup.

然而,由于严格地评估了Python,所以除了避免名称查找之外,没有其他性能提升。

For a very simple expression, I might choose a lambda.

对于一个非常简单的表达式,我可以选择一个。

I also tend to use lambdas when doing interactive Python, to avoid multiple lines when one will do. I use the following sort of code format when I want to pass in an argument to a constructor when calling timeit.repeat:

在使用交互式Python时,我也倾向于使用lambdas,以避免在使用时使用多行。当我想在调用时间时将参数传递给构造函数时,我使用以下代码格式。

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

And now:

现在:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

I believe the slight time difference above can be attributed to the name lookup in return_nullary_function - note that it is very negligible.

我认为上面的细微时间差可以归因于return_nullary_function中的名称查找——注意它是非常微不足道的。

Conclusion

Lambdas are good for informal situations where you want to minimize lines of code in favor of making a singular point.

Lambdas适用于您希望最小化代码行,以创建一个奇异点的非正式场合。

Lambdas are bad for more formal situations where you need clarity for editors of code who will come later, especially in cases where they are non-trivial.

Lambdas对于更正式的情况是不好的,在这种情况下,您需要对稍后会出现的代码编辑器进行清晰的处理,特别是在它们是非平凡的情况下。

We know we are supposed to give our objects good names. How can we do so when the object has no name?

我们知道我们应该给我们的对象起好名字。当对象没有名称时,我们怎么做呢?

For all of these reasons, I prefer to create functions with def instead of with lambda.

出于所有这些原因,我倾向于用def而不是lambda来创建函数。

#12


0  

I agree with nosklo. By the way, even with a use once, throw away function, most of the time you just want to use something from the operator module.

我同意nosklo。顺便说一下,即使有一次使用,扔掉函数,大多数时候你只是想从操作模块中使用一些东西。

E.G :

E。旅客:

You have a function with this signature : myFunction(data, callback function).

您有一个具有此签名的函数:myFunction(数据、回调函数)。

You want to pass a function that add 2 elements.

要传递一个添加两个元素的函数。

Using lambda :

使用λ:

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

The pythonic way :

神谕的道:

import operator
myFunction(data, operator.add)

Or course this is a simple example, but there is a lot of stuff the operator module provides, including the items setters / getters for list and dict. Really cool.

或者这是一个简单的例子,但是操作员模块提供了很多东西,包括列表和命令的setter / getter。

#13


0  

If you are just going to assign the lambda to a variable in the local scope, you may as well use def because it is more readable and can be expanded more easily in the future:

如果您只是将lambda分配给局部范围内的变量,那么您可以使用def,因为它更具可读性,并且在将来可以更容易地扩展:

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

or

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

#14


-1  

lambda is usefull for generating new functions:

用于生成新的函数:

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

#15


-1  

A major difference is that you can not use def functions inline, which is in my opinion the most convenient use case for a lambda function. For example when sorting a list of objects:

一个主要的区别是,您不能在内联中使用def函数,这在我看来是lambda函数最方便的用例。例如,在排序对象列表时:

my_list.sort(key=lambda o: o.x)

I would therefore suggest keeping the use of lambdas to this kind of trivial operations, which also do not really benefit from the automatic documentation provided by naming the function.

因此,我建议将lambdas的使用保留到这种琐碎的操作中,这也不会从命名函数所提供的自动文档中获益。