我大多是使用氧职能,但有时使用嵌套的职能,似乎提供同样的行为。

这里是一些琐碎的例子,它们在功能上做同样的事情,如果被发现在的另一个功能:

Lambda功能

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

嵌套功能

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

>>> b(5)
6

有没有优势,使用一个比其他?(绩效?读?限制?一致性?等等)。

它甚至事?如果它不那么这是否违反Python原则:

"应该有个—和好的唯一显而易见的方式这样做".

有帮助吗?

解决方案

如果需要将 lambda 分配给名称,请改用 def def s只是赋值的语法糖,因此结果是相同的,它们更灵活,更易读。

lambda s可以用于使用一次,丢弃没有名字的函数。

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

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

对于你真的需要一个小函数对象的情况,你应该使用 operator 模块函数,比如 operator.add 而不是 lambda x,y: x + y

如果你仍然需要一些 lambda ,你可以考虑编写一个 def ,只是为了更具可读性。如果函数比 operator 模块的函数更复杂,那么 def 可能更好。

因此,真实世界的 lambda 用例非常罕见。

其他提示

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

第一个是他们做什么和什么他们返回:

  • def是一个关键字不回任何东西,并创建一个'name'在当地的名字空间。

  • lambda是一个关键字返回的一个函数目并不创建一个名称为'在当地的名字空间。

因此,如果你需要打电话的功能,需要一个功能的目的,只有这样,才能做到这一行代码是一个lambda。有没有相当于def.

在一些框架,这实际上是相当常见的;例如,我用的 扭曲的 很多,而且这样做喜欢的东西

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

是相当常见的,更简明,与lambda.

第二个差别是关于什么的实际功能允许这样做。

  • 一个功能的定义的'def'可能包含任何代码
  • 一个功能的定义的'lambda'具有评估来表达,因此不包含声明,如印刷、进口、提高,...

例如,

def p(x): print x

按预期工作,而

lambda x: print x

是语法错误.

当然,也有变通办法替代 printsys.stdout.write, 或 import__import__.但通常你最好要有一个功能,在这种情况。

在这次采访中, Guido van Rossum说他希望他没有让'lambda '进入Python:

  

" 问。您最不满意Python的哪些功能?

  有时候我太快接受了贡献,后来意识到这是一个错误。一个例子是一些函数编程特性,例如lambda函数。 lambda是一个关键字,可以让你创建一个小的匿名函数;内置函数(如map,filter和reduce)在序列类型(如列表)上运行函数。

  在实践中,它并没有那么好。 Python只有两个范围:本地和全局。这使得编写lambda函数变得很痛苦,因为你经常想要在定义lambda的范围内访问变量,但是由于这两个范围你不能。有一种解决方法,但它是一种kludge。通常,在Python中使用for循环而不是乱用lambda函数似乎更容易。地图和朋友只有在已经有了你想要的内置功能时才能正常工作。

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

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

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

对于n = 1000,这里有一个调用函数vs lambda的时间:

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

我同意nosklo的建议:如果你需要给这个函数命名,请使用 def 。我保留 lambda 函数用于我只是将一小段代码传递给另一个函数的情况,例如:

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

性能:

创建一个功能 lambda稍微快一点 比创建它 def.差异是由于 def 创建一个名称中的条目地人表。得到的功能具有同样的执行速度。


可读性:

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)

正如你可以看到, lambda 版本是较短和"轻松"在这个意义上,你只需要增加 lambda v: 到原来的非功能的版本的转换功能的版本。它也是更多的精简。但是记住,一个很大的蟒蛇用户将能混淆lambda法,使你失去了什么长以及真正的复杂性可能会得到回到混乱,从程序员。


限制:

  • lambda 功能可以只能使用一次,除非分配给可变名称。
  • lambda 功能分配给可变的名字没有优势 def 功能。
  • lambda 功能可能是困难或不可能坐.
  • def 职能'的名称必须慎重选择以合理的描述性的,唯一的或至少另有未使用的范围。

一致性:

蟒蛇大多是可以避免的功能编程公约》赞成的程序和更简单的客观的语义。的 lambda 操作者站在直接与此相反的偏向。此外,作为一种替代已经普遍存 def, , lambda 功能增加多样性的语法。一些会考虑,较不一致。


预的现有功能:

正如其他许多用途的 lambda 在该领域可以代替成员 operator 或其他模块。例如:

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

使用预先存在的功能可以使代码的更多的可读的,在许多情况下。


该Python原则:"应该有个—和好的唯一显而易见的方式这样做"

这是类似于 单一来源的真相 原则。不幸的是,单显而易见的方式做-这一原则一直是一种渴望的吸Python,而不是一个真正的指导。考虑的非常强大的阵推导素。它们在功能上等同于 mapfilter 职能:

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

lambdadef 都是相同的。

这是一个问题的意见,但是我要说的是,任何在Python语言用于一般使用不会很明显打破任何东西是"Python"够了。

虽然同意其他答案,但有时它更具可读性。这是一个示例,其中 lambda 派上用场,在用例中我遇到了N维 defaultdict 。这是一个例子:

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

我发现它比为第二维创建 def 更具可读性。这对于更高的尺寸来说更为重要。

lambda的主要用途一直是简单的回调函数,以及map,reduce,filter,它们需要一个函数作为参数。随着列表推导成为常态,并且允许添加,如下所示:

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

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

lambdas的一个重要限制是除了表达式之外它们不能包含任何内容。 lambda表达式几乎不可能产生除了微不足道的副作用之外的任何东西,因为它不能像 def 'ed函数那样拥有丰富的主体。

话虽这么说,Lua影响了我的编程风格,广泛使用了匿名函数,我把它们丢弃了。最重要的是,我倾向于将map / reduce视为抽象运算符,我不会考虑列表推导或生成器,几乎就像我通过使用这些运算符明确地推迟实现决策一样。

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

首先,我强烈反对将 lambda 表达式赋给变量;因为python只有一个特殊的语法(提示, def )。除此之外,lambda的许多用法,即使它们没有得到名称,也有预定义(和更有效)的实现。例如,有问题的示例可以缩写为(1).__ add __ ,而无需将其包装在 lambda def 中。使用 operator itertools functools 模块的某些组合可以满足许多其他常见用途。

更多的优选:lambda功能或嵌套的职能(def)?

有一个优点在于使用一个氧过一个规则的功能(他们是建立在一个表达的),和几个缺点。出于这一原因,我希望创建职能的 def 关键词,而不是与lambda.

第一点-他们是同一类型的对象

Lambda结果同样类型的物体作为一个经常功能

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

由于lambda功能,它们是第一流的对象。

两lambda和职能:

  • 可能通过作为一个论点(同作为一个经常功能)
  • 创建时内外的功能成为一个封闭了,外层功能的当地人

但lambda是默认情况下,缺少一些事情,功能得到通过全功能的定义的语法。

一lamba的 __name__'<lambda>'

Lambda都是匿名的功能,毕竟,使他们不知道自己的名字。

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

因此lambda的不能被看作编程方式在他们的名字空间。

这限制了某些事情。例如, 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

我们可以查找 foo 就好-因为它知道自己的名称:

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

Lambda没有注解和没有文档字符串

基本上,lambda没有记录。让我们重写 foo 要更好的记录:

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

现在,富有文件:

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

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

然而,我们没有同样的机制给予同样的信息lambda:

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

<lambda> lambda (...)

但我们可以破解它们:

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

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

但也有可能是一些错误,搞乱了输出的帮助,虽然。

Lambda只能回返的一种表达

Lambda不能返回复声明,仅仅表达方式。

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

表情可以当然可以相当复杂,如果你尝试 非常 你也许可以完成相同的与lambda,但是增加的复杂性更多的是一种损害,编写明确的代码。

我们使用Python为了清楚的和可维修性。过度使用lambda可以反对。

上为lambda:可以建立在一个单一的表达

这是唯一可能的。因为你可以创建一个lambda的表达,你可以创建内部的一个函数。

创建一种功能的内部呼叫功能可以避免的(廉价)的名称查找,还是一个创造其他地方。

然而,由于蟒是严格评估的,没有任何其他表现得以这样做除了可避免的名称查找。

对于一个非常简单的表达,我可能会选择一个lambda。

我也倾向于使用lambda当做交互式蟒蛇,以避免多个行当一个人会做的。我用以下种代码格式时,我想通过在一个参数的一个构造打电话时 timeit.repeat:

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

和现在:

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

我认为轻微的时间差异上可以归咎于该名称查找 return_nullary_function -注意 非常 可以忽略不计。

结论

Lambda好进行非正式的情况下要最大限度地减少代码行有利于制作一个奇点。

Lambda坏更正式的情况下,你需要的清晰度编码,他们会后来的情况下,尤其在他们无微不足道的。

我们知道我们都应该得到我们的对象的好名字。我们怎么可以这样做的时候对象 没有 名字?

出于所有这些原因,我希望创建职能 def 而不是用 lambda.

  • 计算时间。
  • 功能没有名字。
  • 实现一个功能和多用途的功能。

考虑到一个简单的例子,

# CREATE ONE FUNCTION AND USE IT TO PERFORM MANY OPERATIONS ON SAME TYPE OF DATA STRUCTURE.
def variousUse(a,b=lambda x:x[0]):
    return [b(i) for i in a]

dummyList = [(0,1,2,3),(4,5,6,7),(78,45,23,43)]
variousUse(dummyList)                           # extract first element
variousUse(dummyList,lambda x:[x[0],x[2],x[3]]) # extract specific indexed element
variousUse(dummyList,lambda x:x[0]+x[2])        # add specific elements
variousUse(dummyList,lambda x:x[0]*x[2])        # multiply specific elements

如果您要将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)

我发现的lambdas的一个用途是在调试消息中。

由于lambdas可以被懒惰地评估,你可以使用这样的代码:

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

而不是可能昂贵:

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

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

当然,为了使其按照所描述的方式工作,使用中的日志记录模块必须支持lambdas作为“延迟参数”。 (正如我的记录模块那样)。

同样的想法可能适用于任何其他针对随需应变内容值创建的延迟评估案例。

例如这个自定义三元运算符:

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)

而不是:

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

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

使用lambdas只会评估条件选择的表达式,而不会评估lambdas。

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

我同意nosklo。顺便说一下,即使使用一次,也可以扔掉功能,大部分时间你只想使用操作员模块中的东西。

E.G:

你有一个带有这个签名的函数:myFunction(数据,回调函数)。

您希望传递一个添加2个元素的函数。

使用lambda:

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

pythonic方式:

import operator
myFunction(data, operator.add)

当然这是一个简单的例子,但是运算符模块提供了很多东西,包括列表和字典的setter / getters。真的很酷。

lambda对于生成新函数非常有用:

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

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

my_list.sort(key=lambda o: o.x)
因此,我建议将lambdas用于这种简单的操作,这些操作也无法真正受益于命名函数所提供的自动文档。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top