当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《哪个更适合在Python中使用:lambda函数或嵌套函数('def')?》经验,为你挑选了6个好方法。

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

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

Lambda函数

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

嵌套功能

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

>>> b(5)
6

使用一个优于另一个是否有优势?(性能?可读性?限制?一致性?等)

它甚至重要吗?如果不这样做那就违反了Pythonic原则:

"应该有一种 - 最好只有一种 - 显而易见的方法".

nosklo.. 94

如果您需要将lambda名称指定给名称,请使用def替代名称.defs只是赋值的语法糖,所以结果是一样的,它们更灵活,更易读.

lambdas可以使用一次,扔掉没有名字的函数.

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

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

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

如果你仍然需要一些lambda不被覆盖的东西,你可以考虑写一个def,只是为了更具可读性.如果函数比operator模块上的函数更复杂,def则可能更好.

所以,现实世界的好用lambda例非常罕见.



1> nosklo..:

如果您需要将lambda名称指定给名称,请使用def替代名称.defs只是赋值的语法糖,所以结果是一样的,它们更灵活,更易读.

lambdas可以使用一次,扔掉没有名字的函数.

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

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

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

如果你仍然需要一些lambda不被覆盖的东西,你可以考虑写一个def,只是为了更具可读性.如果函数比operator模块上的函数更复杂,def则可能更好.

所以,现实世界的好用lambda例非常罕见.


我同意何时使用`lambda`的答案,但我不同意这是"非常罕见",对于`sorted`或`itertools.groupby`等关键函数来说很常见,例如`sorted(['a1 ','b0'],key = lambda x:int(x [1]))`

2> Thomas Vande..:

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

第一个是关于他们做什么以及他们返回什么:

def是一个不返回任何内容的关键字,并在本地名称空间中创建"名称".

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

因此,如果你需要调用一个带有函数对象的函数,在一行python代码中执行该操作的唯一方法是使用lambda.没有与def相当的东西.

在某些框架中,这实际上很常见; 例如,我使用Twisted很多,所以做了类似的事情

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

很常见,而且对lambdas更简洁.

第二个区别是关于允许实际功能的内容.

用'def'定义的函数可以包含任何python代码

用'lambda'定义的函数必须求值为表达式,因此不能包含print,import,raise等语句.

例如,

def p(x): print x

按预期工作,而

lambda x: print x

是一个SyntaxError.

当然,也有变通方法-代替printsys.stdout.write,或import__import__.但在这种情况下,通常你最好使用一个函数.



3> Chris Lawlor..:

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

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


请注意,访谈相当陈旧,Python早就添加了嵌套范围,这使得他对lambda的论证不再具有相关性.我确定他仍然感到遗憾lambda,但还不足以在Python 3.0中删除它.
真的你的例子应该是反对单行的论据,而不是lambdas.此外,您应该使用内置求和函数而不是使用lambda:str(sum(map(lambda x:x**x,range(1001))))[: - 10]

4> Andy Hayden..:

对于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


有趣的是看到lambda和定义版本大致相同.最后一次测试需要更多时间,因为python可能需要在每次定义lambda函数时分配空间.

5> Dan Lenski..:

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

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


在map/lambda的大多数组合中,您可以使用列表推导或更合适的函数替换它.例如,"map(sum,a)"或"[x [0] + x [1] for x in a""

6> Pi Marillion..:

性能:

以创建一个功能lambda速度稍快比创建它def.不同之处def在于在locals表中创建了一个名称条目.结果函数具有相同的执行速度.


可读性:

对于大多数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)

正如您所看到的,lambda版本更短且更"简单",因为您只需要添加lambda v:到原始的非功能版本即可转换为功能版本.它也更简洁.但是请记住,许多Python用户会被lambda语法所迷惑,所以你失去的长度和真正的复杂性可能会被其他编码人员混淆.


限制:

lambda 函数只能使用一次,除非分配给变量名.

lambda分配给变量名的def函数没有函数优势.

lambda 功能可能很难或不可能发泡.

def 必须仔细选择功能的名称,使其具有合理的描述性和独特性,或至少在范围内不使用.


一致性:

Python主要避免使用函数式编程约定,而采用程序性和简单的客观语义.该lambda操作员站直接的对比这种偏见.此外,作为已经流行的替代方案def,该lambda函数为您的语法增加了多样性.有人会认为不太一致.


预先存在的功能:

如其他人所指出的lambda,本领域的许多用途可以由该operator模块或其他模块的成员代替.例如:

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

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


Pythonic原则:"应该有一个 - 最好只有一个 - 显而易见的方法"

这与真理学说的单一来源相似.不幸的是,单一显而易见的原则一直是Python的渴望,而不是真正的指导原则.考虑一下Python中非常强大的数组解析.它们在功能上等同于mapfilter功能:

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

lambda并且def是一样的.

这是一个意见问题,但我会说,用于一般用途的Python语言中没有明显破坏任何东西的东西都是"Pythonic".

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有