标签归档:lambda

Python中没有多行Lambda:为什么不呢?

问题:Python中没有多行Lambda:为什么不呢?

我听说它说不能在Python中添加多行lambda,因为它们会在语法上与Python中的其他语法结构发生冲突。我今天在公共汽车上考虑这个问题,意识到我想不出一个与多行lambda冲突的Python结构。考虑到我非常了解该语言,这令我感到惊讶。

现在,我确定Guido有一个理由不在语言中包含多行lambda,而是出于好奇:在什么情况下包含多行lambda会导致歧义?我所听到的是正确的,还是Python不允许多行lambda的其他原因?

I’ve heard it said that multiline lambdas can’t be added in Python because they would clash syntactically with the other syntax constructs in Python. I was thinking about this on the bus today and realized I couldn’t think of a single Python construct that multiline lambdas clash with. Given that I know the language pretty well, this surprised me.

Now, I’m sure Guido had a reason for not including multiline lambdas in the language, but out of curiosity: what’s a situation where including a multiline lambda would be ambiguous? Is what I’ve heard true, or is there some other reason that Python doesn’t allow multiline lambdas?


回答 0

请看以下内容:

map(multilambda x:
      y=x+1
      return y
   , [1,2,3])

这是lambda返回(y, [1,2,3])(因此映射仅获取一个参数,从而导致错误)吗?还是返回y?还是语法错误,因为新行上的逗号放置不正确?Python如何知道您想要什么?

在括号内,缩进对于python并不重要,因此您不能明确地使用多行。

这只是一个简单的例子,可能还有更多示例。

Look at the following:

map(multilambda x:
      y=x+1
      return y
   , [1,2,3])

Is this a lambda returning (y, [1,2,3]) (thus map only gets one parameter, resulting in an error)? Or does it return y? Or is it a syntax error, because the comma on the new line is misplaced? How would Python know what you want?

Within the parens, indentation doesn’t matter to python, so you can’t unambiguously work with multilines.

This is just a simple one, there’s probably more examples.


回答 1

Guido van Rossum(Python的发明者)自己在一个旧的博客文章中回答了这个确切的问题。
基本上,他承认这在理论上是可行的,但是任何建议的解决方案都是非Python的:

“但是,对于我来说,任何提议的解决方案的复杂性对我来说都是巨大的:它要求解析器(或更确切地说是词法分析器)能够在缩进敏感模式和缩进不敏感模式之间来回切换,并保持堆栈技术上可以解决所有问题(已经有一堆可以概括的缩进级别了。)但是,这些都不让我直觉,这简直就是鲁伯·戈德堡的精妙之处。”

Guido van Rossum (the inventor of Python) answers this exact question himself in an old blog post.
Basically, he admits that it’s theoretically possible, but that any proposed solution would be un-Pythonic:

“But the complexity of any proposed solution for this puzzle is immense, to me: it requires the parser (or more precisely, the lexer) to be able to switch back and forth between indent-sensitive and indent-insensitive modes, keeping a stack of previous modes and indentation level. Technically that can all be solved (there’s already a stack of indentation levels that could be generalized). But none of that takes away my gut feeling that it is all an elaborate Rube Goldberg contraption.”


回答 2

通常这很丑陋(但有时替代方法甚至更丑陋),因此一种解决方法是制作一个大括号表达式:

lambda: (
    doFoo('abc'),
    doBar(123),
    doBaz())

不过,它不会接受任何分配,因此您必须事先准备数据。我发现这个有用的地方是PySide包装器,有时在其中有简短的回调。编写其他成员函数将更加难看。通常,您将不需要此。

例:

pushButtonShowDialog.clicked.connect(
    lambda: (
    field1.clear(),
    spinBox1.setValue(0),
    diag.show())

This is generally very ugly (but sometimes the alternatives are even more ugly), so a workaround is to make a braces expression:

lambda: (
    doFoo('abc'),
    doBar(123),
    doBaz())

It won’t accept any assignments though, so you’ll have to prepare data beforehand. The place I found this useful is the PySide wrapper, where you sometimes have short callbacks. Writing additional member functions would be even more ugly. Normally you won’t need this.

Example:

pushButtonShowDialog.clicked.connect(
    lambda: (
    field1.clear(),
    spinBox1.setValue(0),
    diag.show())

回答 3

一些相关链接:

一段时间以来,我一直在关注Reia的开发,该开发最初也将基于Python的基于缩进的语法与Ruby块一起使用,全部都在Erlang之上。但是,设计师最终放弃了缩进敏感性,他写的有关该决定的文章包括有关他在缩进+多行块中遇到的问题的讨论,以及他对Guido的设计问题/决定的越来越多的赞赏:

http://www.unlimitednovelty.com/2009/03/indentation-sensitiveivity-post-mortem.html

另外,这是一个关于Python中Ruby样式块的有趣建议,我在Guido上发布了一个响应,但没有将其实际击倒(尽管不确定是否有任何后续击落):

http://tav.espians.com/ruby-style-blocks-in-python.html

A couple of relevant links:

For a while, I was following the development of Reia, which was initially going to have Python’s indentation based syntax with Ruby blocks too, all on top of Erlang. But, the designer wound up giving up on indentation sensitivity, and this post he wrote about that decision includes a discussion about problems he ran into with indentation + multi-line blocks, and an increased appreciation he gained for Guido’s design issues/decisions:

http://www.unlimitednovelty.com/2009/03/indentation-sensitivity-post-mortem.html

Also, here’s an interesting proposal for Ruby-style blocks in Python I ran across where Guido posts a response w/o actually shooting it down (not sure whether there has been any subsequent shoot down, though):

http://tav.espians.com/ruby-style-blocks-in-python.html


回答 4

[编辑]阅读此答案。它解释了为什么多行lambda不是问题。

简而言之,这是不可思议的。来自Guido van Rossum的博客文章:

我发现任何在表达式中间嵌入基于缩进的块的解决方案都是不可接受的。由于我发现语句分组的替代语法(例如花括号或begin / end关键字)同样不可接受,因此,这几乎使多行lambda成为无法解决的难题。

[Edit] Read this answer. It explains why multiline lambda is not a thing.

Simply put, it’s unpythonic. From Guido van Rossum’s blog post:

I find any solution unacceptable that embeds an indentation-based block in the middle of an expression. Since I find alternative syntax for statement grouping (e.g. braces or begin/end keywords) equally unacceptable, this pretty much makes a multi-line lambda an unsolvable puzzle.


回答 5

让我向您介绍一个光荣却可怕的技巧:

import types

def _obj():
  return lambda: None

def LET(bindings, body, env=None):
  '''Introduce local bindings.
  ex: LET(('a', 1,
           'b', 2),
          lambda o: [o.a, o.b])
  gives: [1, 2]

  Bindings down the chain can depend on
  the ones above them through a lambda.
  ex: LET(('a', 1,
           'b', lambda o: o.a + 1),
          lambda o: o.b)
  gives: 2
  '''
  if len(bindings) == 0:
    return body(env)

  env = env or _obj()
  k, v = bindings[:2]
  if isinstance(v, types.FunctionType):
    v = v(env)

  setattr(env, k, v)
  return LET(bindings[2:], body, env)

您现在可以按以下LET方式使用此表单:

map(lambda x: LET(('y', x + 1,
                   'z', x - 1),
                  lambda o: o.y * o.z),
    [1, 2, 3])

这使: [0, 3, 8]

Let me present to you a glorious but terrifying hack:

import types

def _obj():
  return lambda: None

def LET(bindings, body, env=None):
  '''Introduce local bindings.
  ex: LET(('a', 1,
           'b', 2),
          lambda o: [o.a, o.b])
  gives: [1, 2]

  Bindings down the chain can depend on
  the ones above them through a lambda.
  ex: LET(('a', 1,
           'b', lambda o: o.a + 1),
          lambda o: o.b)
  gives: 2
  '''
  if len(bindings) == 0:
    return body(env)

  env = env or _obj()
  k, v = bindings[:2]
  if isinstance(v, types.FunctionType):
    v = v(env)

  setattr(env, k, v)
  return LET(bindings[2:], body, env)

You can now use this LET form as such:

map(lambda x: LET(('y', x + 1,
                   'z', x - 1),
                  lambda o: o.y * o.z),
    [1, 2, 3])

which gives: [0, 3, 8]


回答 6

我在一些项目中实践这种肮脏的技巧感到内which,这有点简单:

    lambda args...:( expr1, expr2, expr3, ...,
            exprN, returnExpr)[-1]

我希望您能找到一种保持pythonic的方法,但是如果您必须这样做的话,那么会比使用exec和操作globals减轻痛苦。

I’m guilty of practicing this dirty hack in some of my projects which is bit simpler:

    lambda args...:( expr1, expr2, expr3, ...,
            exprN, returnExpr)[-1]

I hope you can find a way to stay pythonic but if you have to do it this less painful than using exec and manipulating globals.


回答 7

让我尝试解决@balpha解析问题。我会在多行lamda周围使用括号。如果没有括号,则lambda定义为贪婪的。所以lambda在

map(lambda x:
      y = x+1
      z = x-1
      y*z,
    [1,2,3]))

返回一个函数,该函数返回 (y*z, [1,2,3])

map((lambda x:
      y = x+1
      z = x-1
      y*z)
    ,[1,2,3]))

手段

map(func, [1,2,3])

其中func是返回y * z的多行lambda。那样有用吗?

Let me try to tackle @balpha parsing problem. I would use parentheses around the multiline lamda. If there is no parentheses, the lambda definition is greedy. So the lambda in

map(lambda x:
      y = x+1
      z = x-1
      y*z,
    [1,2,3]))

returns a function that returns (y*z, [1,2,3])

But

map((lambda x:
      y = x+1
      z = x-1
      y*z)
    ,[1,2,3]))

means

map(func, [1,2,3])

where func is the multiline lambda that return y*z. Does that work?


回答 8

(对于仍对该主题感兴趣的任何人。)

考虑一下这一点(即使在“多行” lambda中的其他语句中甚至使用了语句的返回值,尽管这很呕吐;-)

>>> def foo(arg):
...     result = arg * 2;
...     print "foo(" + str(arg) + ") called: " + str(result);
...     return result;
...
>>> f = lambda a, b, state=[]: [
...     state.append(foo(a)),
...     state.append(foo(b)),
...     state.append(foo(state[0] + state[1])),
...     state[-1]
... ][-1];
>>> f(1, 2);
foo(1) called: 2
foo(2) called: 4
foo(6) called: 12
12

(For anyone still interested in the topic.)

Consider this (includes even usage of statements’ return values in further statements within the “multiline” lambda, although it’s ugly to the point of vomiting ;-)

>>> def foo(arg):
...     result = arg * 2;
...     print "foo(" + str(arg) + ") called: " + str(result);
...     return result;
...
>>> f = lambda a, b, state=[]: [
...     state.append(foo(a)),
...     state.append(foo(b)),
...     state.append(foo(state[0] + state[1])),
...     state[-1]
... ][-1];
>>> f(1, 2);
foo(1) called: 2
foo(2) called: 4
foo(6) called: 12
12

回答 9

您可以简单地使用斜杠(\如果您的lambda函数有多行,则)

例:

mx = lambda x, y: x if x > y \
     else y
print(mx(30, 20))

Output: 30

You can simply use slash (\) if you have multiple lines for your lambda function

Example:

mx = lambda x, y: x if x > y \
     else y
print(mx(30, 20))

Output: 30

回答 10

我从python开始,但是来自Javascript最明显的方法是将表达式提取为函数…。

人为的例子,乘法表达式(x*2)被提取为函数,因此我可以使用多行:

def multiply(x):
  print('I am other line')
  return x*2

r = map(lambda x : multiply(x), [1, 2, 3, 4])
print(list(r))

https://repl.it/@datracka/python-lambda-function

也许它不能完全回答这个问题,即那是如何在lambda表达式本身中执行多行操作,但是如果有人得到此线程来查找如何调试该表达式(像我一样),我认为这会有所帮助

I am starting with python but coming from Javascript the most obvious way is extract the expression as a function….

Contrived example, multiply expression (x*2) is extracted as function and therefore I can use multiline:

def multiply(x):
  print('I am other line')
  return x*2

r = map(lambda x : multiply(x), [1, 2, 3, 4])
print(list(r))

https://repl.it/@datracka/python-lambda-function

Maybe it does not answer exactly the question if that was how to do multiline in the lambda expression itself, but in case somebody gets this thread looking how to debug the expression (like me) I think it will help


回答 11

关于丑陋的黑客,您始终可以使用exec和常规函数的组合来定义多行函数,如下所示:

f = exec('''
def mlambda(x, y):
    d = y - x
    return d * d
''', globals()) or mlambda

您可以将其包装为以下函数:

def mlambda(signature, *lines):
    exec_vars = {}
    exec('def mlambda' + signature + ':\n' + '\n'.join('\t' + line for line in lines), exec_vars)
    return exec_vars['mlambda']

f = mlambda('(x, y)',
            'd = y - x',
            'return d * d')

On the subject of ugly hacks, you can always use a combination of exec and a regular function to define a multiline function like this:

f = exec('''
def mlambda(x, y):
    d = y - x
    return d * d
''', globals()) or mlambda

You can wrap this into a function like:

def mlambda(signature, *lines):
    exec_vars = {}
    exec('def mlambda' + signature + ':\n' + '\n'.join('\t' + line for line in lines), exec_vars)
    return exec_vars['mlambda']

f = mlambda('(x, y)',
            'd = y - x',
            'return d * d')

回答 12

我只是在玩些游戏,以尝试对reduce进行字典理解,并提出这个内胆技巧:

In [1]: from functools import reduce
In [2]: reduce(lambda d, i: (i[0] < 7 and d.__setitem__(*i[::-1]), d)[-1], [{}, *{1:2, 3:4, 5:6, 7:8}.items()])                                                                                                                                                                 
Out[3]: {2: 1, 4: 3, 6: 5}

我只是想做与此Javascript dict理解相同的事情:https : //stackoverflow.com/a/11068265

I was just playing a bit to try to make a dict comprehension with reduce, and come up with this one liner hack:

In [1]: from functools import reduce
In [2]: reduce(lambda d, i: (i[0] < 7 and d.__setitem__(*i[::-1]), d)[-1], [{}, *{1:2, 3:4, 5:6, 7:8}.items()])                                                                                                                                                                 
Out[3]: {2: 1, 4: 3, 6: 5}

I was just trying to do the same as what was done in this Javascript dict comprehension: https://stackoverflow.com/a/11068265


回答 13

这是多行lambda的更有趣的实现。由于python如何使用缩进来构造代码,因此无法实现。

但是幸运的是,可以使用数组和括号禁用缩进格式。

正如已经指出的那样,您可以这样编写代码:

lambda args: (expr1, expr2,... exprN)

从理论上讲,如果可以保证从左到右进行求值,那么它会起作用,但是仍然会丢失从一个表达式传递到另一个表达式的值。

实现较为冗长的方法的一种方法是

lambda args: [lambda1, lambda2, ..., lambdaN]

每个lambda接收前一个参数的位置。

def let(*funcs):
    def wrap(args):
        result = args                                                                                                                                                                                                                         
        for func in funcs:
            if not isinstance(result, tuple):
                result = (result,)
            result = func(*result)
        return result
    return wrap

这种方法使您可以编写有点像Lisp / scheme的东西。

所以你可以这样写:

let(lambda x, y: x+y)((1, 2))

可以使用更复杂的方法来计算斜边

lst = [(1,2), (2,3)]
result = map(let(
  lambda x, y: (x**2, y**2),
  lambda x, y: (x + y) ** (1/2)
), lst)

这将返回一个标量数字列表,因此可用于将多个值减少为一个。

拥有那么多lambda肯定不会非常有效,但是如果您受到限制,那么它可能是快速完成某项工作并将其重写为实际函数的好方法。

Here’s a more interesting implementation of multi line lambdas. It’s not possible to achieve because of how python use indents as a way to structure code.

But luckily for us, indent formatting can be disabled using arrays and parenthesis.

As some already pointed out, you can write your code as such:

lambda args: (expr1, expr2,... exprN)

In theory if you’re guaranteed to have evaluation from left to right it would work but you still lose values being passed from one expression to an other.

One way to achieve that which is a bit more verbose is to have

lambda args: [lambda1, lambda2, ..., lambdaN]

Where each lambda receives arguments from the previous one.

def let(*funcs):
    def wrap(args):
        result = args                                                                                                                                                                                                                         
        for func in funcs:
            if not isinstance(result, tuple):
                result = (result,)
            result = func(*result)
        return result
    return wrap

This method let you write something that is a bit lisp/scheme like.

So you can write things like this:

let(lambda x, y: x+y)((1, 2))

A more complex method could be use to compute the hypotenuse

lst = [(1,2), (2,3)]
result = map(let(
  lambda x, y: (x**2, y**2),
  lambda x, y: (x + y) ** (1/2)
), lst)

This will return a list of scalar numbers so it can be used to reduce multiple values to one.

Having that many lambda is certainly not going to be very efficient but if you’re constrained it can be a good way to get something done quickly then rewrite it as an actual function later.


回答 14

因为lambda函数应该是单行的,因此它是函数的最简单形式, an entrance, then return

because a lambda function is supposed to be one-lined, as its the simplest form of a function, an entrance, then return


查找列表的平均值

问题:查找列表的平均值

我必须在Python中找到列表的平均值。到目前为止,这是我的代码

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
print reduce(lambda x, y: x + y, l)

我已经知道了,所以它可以将列表中的值加在一起,但是我不知道如何将其划分为它们?

I have to find the average of a list in Python. This is my code so far

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
print reduce(lambda x, y: x + y, l)

I’ve got it so it adds together the values in the list, but I don’t know how to make it divide into them?


回答 0

在Python 3.4+上,您可以使用 statistics.mean()

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]

import statistics
statistics.mean(l)  # 20.11111111111111

在旧版本的Python上,您可以执行

sum(l) / len(l)

在Python 2上,您需要转换len为浮点数才能进行浮点数除法

sum(l) / float(len(l))

无需使用reduce。它慢得多,并在Python 3 中删除

On Python 3.4+ you can use statistics.mean()

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]

import statistics
statistics.mean(l)  # 20.11111111111111

On older versions of Python you can do

sum(l) / len(l)

On Python 2 you need to convert len to a float to get float division

sum(l) / float(len(l))

There is no need to use reduce. It is much slower and was removed in Python 3.


回答 1

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
sum(l) / len(l)
l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
sum(l) / len(l)

回答 2

您可以使用numpy.mean

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]

import numpy as np
print(np.mean(l))

You can use numpy.mean:

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]

import numpy as np
print(np.mean(l))

回答 3

一个统计模块已经加入到了Python 3.4。它具有计算平均值的功能,称为均值。您提供的列表的示例为:

from statistics import mean
l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
mean(l)

A statistics module has been added to python 3.4. It has a function to calculate the average called mean. An example with the list you provided would be:

from statistics import mean
l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
mean(l)

回答 4

reduce()当Python具有完美的sum()功能时,为什么要使用此功能?

print sum(l) / float(len(l))

float()必须强制Python执行浮点除法。)

Why would you use reduce() for this when Python has a perfectly cromulent sum() function?

print sum(l) / float(len(l))

(The float() is necessary to force Python to do a floating-point division.)


回答 5

如果您使用的是python> = 3.4,则有一个统计资料库

https://docs.python.org/3/library/statistics.html

您可以使用这种卑鄙的方法。假设您有一个要查找均值的数字列表:-

list = [11, 13, 12, 15, 17]
import statistics as s
s.mean(list)

它还有其他方法,如stdev,方差,众数,谐波均值,中位数等,这些方法也非常有用。

There is a statistics library if you are using python >= 3.4

https://docs.python.org/3/library/statistics.html

You may use it’s mean method like this. Let’s say you have a list of numbers of which you want to find mean:-

list = [11, 13, 12, 15, 17]
import statistics as s
s.mean(list)

It has other methods too like stdev, variance, mode, harmonic mean, median etc which are too useful.


回答 6

除了将其强制转换为浮点数外,还可以在总和上加上0.0:

def avg(l):
    return sum(l, 0.0) / len(l)

Instead of casting to float, you can add 0.0 to the sum:

def avg(l):
    return sum(l, 0.0) / len(l)

回答 7

sum(l) / float(len(l)) 是正确的答案,但仅出于完整性考虑,您可以通过一次减少来计算平均值:

>>> reduce(lambda x, y: x + y / float(len(l)), l, 0)
20.111111111111114

请注意,这可能会导致轻微的舍入错误:

>>> sum(l) / float(len(l))
20.111111111111111

sum(l) / float(len(l)) is the right answer, but just for completeness you can compute an average with a single reduce:

>>> reduce(lambda x, y: x + y / float(len(l)), l, 0)
20.111111111111114

Note that this can result in a slight rounding error:

>>> sum(l) / float(len(l))
20.111111111111111

回答 8

我尝试使用上面的选项,但是没有用。尝试这个:

from statistics import mean

n = [11, 13, 15, 17, 19]

print(n)
print(mean(n))

在python 3.5上工作

I tried using the options above but didn’t work. Try this:

from statistics import mean

n = [11, 13, 15, 17, 19]

print(n)
print(mean(n))

worked on python 3.5


回答 9

或使用pandasSeries.mean方法:

pd.Series(sequence).mean()

演示:

>>> import pandas as pd
>>> l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
>>> pd.Series(l).mean()
20.11111111111111
>>> 

从文档:

Series.mean(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

这是文档:

https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.mean.html

以及整个文档:

https://pandas.pydata.org/pandas-docs/stable/10min.html

Or use pandas‘s Series.mean method:

pd.Series(sequence).mean()

Demo:

>>> import pandas as pd
>>> l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
>>> pd.Series(l).mean()
20.11111111111111
>>> 

From the docs:

Series.mean(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

And here is the docs for this:

https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.mean.html

And the whole documentation:

https://pandas.pydata.org/pandas-docs/stable/10min.html


回答 10

在Udacity的问题中,我也有类似的问题要解决。我编码的不是内置函数:

def list_mean(n):

    summing = float(sum(n))
    count = float(len(n))
    if n == []:
        return False
    return float(summing/count)

比平常更长的时间,但是对于初学者来说,这是一个很大的挑战。

I had a similar question to solve in a Udacity´s problems. Instead of a built-in function i coded:

def list_mean(n):

    summing = float(sum(n))
    count = float(len(n))
    if n == []:
        return False
    return float(summing/count)

Much more longer than usual but for a beginner its quite challenging.


回答 11

作为一个初学者,我只是编写了这样的代码:

L = [15, 18, 2, 36, 12, 78, 5, 6, 9]

total = 0

def average(numbers):
    total = sum(numbers)
    total = float(total)
    return total / len(numbers)

print average(L)

as a beginner, I just coded this:

L = [15, 18, 2, 36, 12, 78, 5, 6, 9]

total = 0

def average(numbers):
    total = sum(numbers)
    total = float(total)
    return total / len(numbers)

print average(L)

回答 12

如果您想获得的不仅仅是平均值(也就是平均值),您可以查看scipy统计信息

from scipy import stats
l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
print(stats.describe(l))

# DescribeResult(nobs=9, minmax=(2, 78), mean=20.11111111111111, 
# variance=572.3611111111111, skewness=1.7791785448425341, 
# kurtosis=1.9422716419666397)

If you wanted to get more than just the mean (aka average) you might check out scipy stats

from scipy import stats
l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
print(stats.describe(l))

# DescribeResult(nobs=9, minmax=(2, 78), mean=20.11111111111111, 
# variance=572.3611111111111, skewness=1.7791785448425341, 
# kurtosis=1.9422716419666397)

回答 13

为了reduce用于获得运行平均值,您需要跟踪总数,但也要跟踪到目前为止看到的元素总数。由于这不是列表中的琐碎元素,因此您还必须传递reduce一个额外的参数以使其折叠。

>>> l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
>>> running_average = reduce(lambda aggr, elem: (aggr[0] + elem, aggr[1]+1), l, (0.0,0))
>>> running_average[0]
(181.0, 9)
>>> running_average[0]/running_average[1]
20.111111111111111

In order to use reduce for taking a running average, you’ll need to track the total but also the total number of elements seen so far. since that’s not a trivial element in the list, you’ll also have to pass reduce an extra argument to fold into.

>>> l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
>>> running_average = reduce(lambda aggr, elem: (aggr[0] + elem, aggr[1]+1), l, (0.0,0))
>>> running_average[0]
(181.0, 9)
>>> running_average[0]/running_average[1]
20.111111111111111

回答 14

两者都可以为您提供接近整数或至少10个十进制值的相似值。但是,如果您真正考虑的是长浮点值,则两者可能会有所不同。方法可能因您要实现的目标而异。

>>> l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
>>> print reduce(lambda x, y: x + y, l) / len(l)
20
>>> sum(l)/len(l)
20

浮动值

>>> print reduce(lambda x, y: x + y, l) / float(len(l))
20.1111111111
>>> print sum(l)/float(len(l))
20.1111111111

@安德鲁·克拉克(Andrew Clark)的发言是正确的。

Both can give you close to similar values on an integer or at least 10 decimal values. But if you are really considering long floating values both can be different. Approach can vary on what you want to achieve.

>>> l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
>>> print reduce(lambda x, y: x + y, l) / len(l)
20
>>> sum(l)/len(l)
20

Floating values

>>> print reduce(lambda x, y: x + y, l) / float(len(l))
20.1111111111
>>> print sum(l)/float(len(l))
20.1111111111

@Andrew Clark was correct on his statement.


回答 15

假设

x = [[-5.01,-5.43,1.08,0.86,-2.67,4.94,-2.51,-2.25,5.56,1.03], [-8.12,-3.48,-5.52,-3.78,0.63,3.29,2.09,-2.13,2.86,-3.33], [-3.68,-3.54,1.66,-4.11,7.39,2.08,-2.59,-6.94,-2.26,4.33]]

您会注意到它的x尺寸为3 * 10,如果您需要mean进入每一行,则可以键入

theMean = np.mean(x1,axis=1)

别忘了 import numpy as np

suppose that

x = [[-5.01,-5.43,1.08,0.86,-2.67,4.94,-2.51,-2.25,5.56,1.03], [-8.12,-3.48,-5.52,-3.78,0.63,3.29,2.09,-2.13,2.86,-3.33], [-3.68,-3.54,1.66,-4.11,7.39,2.08,-2.59,-6.94,-2.26,4.33]]

you can notice that x has dimension 3*10 if you need to get the mean to each row you can type this

theMean = np.mean(x1,axis=1)

don’t forget to import numpy as np


回答 16

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]

l = map(float,l)
print '%.2f' %(sum(l)/len(l))
l = [15, 18, 2, 36, 12, 78, 5, 6, 9]

l = map(float,l)
print '%.2f' %(sum(l)/len(l))

回答 17

使用以下PYTHON代码在列表中查找平均值:

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
print(sum(l)//len(l))

试试这个很容易。

Find the average in list By using the following PYTHON code:

l = [15, 18, 2, 36, 12, 78, 5, 6, 9]
print(sum(l)//len(l))

try this it easy.


回答 18

print reduce(lambda x, y: x + y, l)/(len(l)*1.0)

或喜欢以前发布的

sum(l)/(len(l)*1.0)

1.0是确保获得浮点除法

print reduce(lambda x, y: x + y, l)/(len(l)*1.0)

or like posted previously

sum(l)/(len(l)*1.0)

The 1.0 is to make sure you get a floating point division


回答 19

结合以上几个答案,我提出了以下与reduce一起使用的方法,并且不假定您在reduce L函数中可用:

from operator import truediv

L = [15, 18, 2, 36, 12, 78, 5, 6, 9]

def sum_and_count(x, y):
    try:
        return (x[0] + y, x[1] + 1)
    except TypeError:
        return (x + y, 2)

truediv(*reduce(sum_and_count, L))

# prints 
20.11111111111111

Combining a couple of the above answers, I’ve come up with the following which works with reduce and doesn’t assume you have L available inside the reducing function:

from operator import truediv

L = [15, 18, 2, 36, 12, 78, 5, 6, 9]

def sum_and_count(x, y):
    try:
        return (x[0] + y, x[1] + 1)
    except TypeError:
        return (x + y, 2)

truediv(*reduce(sum_and_count, L))

# prints 
20.11111111111111

回答 20

我想添加另一种方法

import itertools,operator
list(itertools.accumulate(l,operator.add)).pop(-1) / len(l)

I want to add just another approach

import itertools,operator
list(itertools.accumulate(l,operator.add)).pop(-1) / len(l)

回答 21

numbers = [0,1,2,3]

numbers[0] = input("Please enter a number")

numbers[1] = input("Please enter a second number")

numbers[2] = input("Please enter a third number")

numbers[3] = input("Please enter a fourth number")

print (numbers)

print ("Finding the Avarage")

avarage = int(numbers[0]) + int(numbers[1]) + int(numbers[2]) + int(numbers [3]) / 4

print (avarage)
numbers = [0,1,2,3]

numbers[0] = input("Please enter a number")

numbers[1] = input("Please enter a second number")

numbers[2] = input("Please enter a third number")

numbers[3] = input("Please enter a fourth number")

print (numbers)

print ("Finding the Avarage")

avarage = int(numbers[0]) + int(numbers[1]) + int(numbers[2]) + int(numbers [3]) / 4

print (avarage)

为什么Python Lambda有用?[关闭]

问题:为什么Python Lambda有用?[关闭]

我正在尝试找出Python lambda。lambda是在现实生活中应该被遗忘的那些“有趣”语言项目之一吗?

我确定在某些情况下可能需要使用它,但是鉴于它的晦涩之处,在将来的版本中重新定义了它的潜力(根据各种定义我的假设)以及降低的编码清晰度-是否应该被避免?

这让我想起了C类型的溢出(缓冲区溢出)-指向顶部变量,并通过重载来设置其他字段值。感觉像是技术娴熟的演艺风格,但却是维护编码员的噩梦。

I’m trying to figure out Python lambdas. Is lambda one of those “interesting” language items that in real life should be forgotten?

I’m sure there are some edge cases where it might be needed, but given the obscurity of it, the potential of it being redefined in future releases (my assumption based on the various definitions of it) and the reduced coding clarity – should it be avoided?

This reminds me of overflowing (buffer overflow) of C types – pointing to the top variable and overloading to set the other field values. It feels like sort of a techie showmanship but maintenance coder nightmare.


回答 0

您是在谈论lambda函数吗?喜欢

lambda x: x**2 + 2*x - 5

这些东西实际上非常有用。Python支持一种称为函数式编程的编程风格,您可以在其中将函数传递给其他函数来完成工作。例:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

设置mult3[3, 6, 9],原始列表的那些元素是3的倍数。这比(可能会说清楚)短于

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

当然,在这种情况下,您可以做与列表理解相同的事情:

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(或什至range(3,10,3)),但是在许多其他更复杂的用例中,您不能使用列表推导,而lambda函数可能是写出东西的最短方法。

  • 从另一个函数返回一个函数

    >>> def transform(n):
    ...     return lambda x: x + n
    ...
    >>> f = transform(3)
    >>> f(4)
    7

    这通常用于创建函数包装器,例如Python的装饰器。

  • 将可迭代序列的元素与 reduce()

    >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    '1, 2, 3, 4, 5, 6, 7, 8, 9'
  • 按备用键排序

    >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
    [5, 4, 6, 3, 7, 2, 8, 1, 9]

我定期使用lambda函数。我花了一些时间来适应它们,但最终我了解到它们是语言中非常有价值的一部分。

Are you talking about lambda functions? Like

lambda x: x**2 + 2*x - 5

Those things are actually quite useful. Python supports a style of programming called functional programming where you can pass functions to other functions to do stuff. Example:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

sets mult3 to [3, 6, 9], those elements of the original list that are multiples of 3. This is shorter (and, one could argue, clearer) than

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

Of course, in this particular case, you could do the same thing as a list comprehension:

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(or even as range(3,10,3)), but there are many other, more sophisticated use cases where you can’t use a list comprehension and a lambda function may be the shortest way to write something out.

  • Returning a function from another function

    >>> def transform(n):
    ...     return lambda x: x + n
    ...
    >>> f = transform(3)
    >>> f(4)
    7
    

    This is often used to create function wrappers, such as Python’s decorators.

  • Combining elements of an iterable sequence with reduce()

    >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    '1, 2, 3, 4, 5, 6, 7, 8, 9'
    
  • Sorting by an alternate key

    >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
    [5, 4, 6, 3, 7, 2, 8, 1, 9]
    

I use lambda functions on a regular basis. It took me a while to get used to them, but eventually I came to understand that they’re a very valuable part of the language.


回答 1

lambda只是一种幻想的表达方式function。除了它的名字,没有什么晦涩,令人生畏或神秘的东西。阅读以下行时,请以替换lambdafunction

>>> f = lambda x: x + 1
>>> f(3)
4

它只是定义的功能x。其他一些语言(如R)则明确指出:

> f = function(x) { x + 1 }
> f(3)
4

你看?这是编程中最自然的事情之一。

lambda is just a fancy way of saying function. Other than its name, there is nothing obscure, intimidating or cryptic about it. When you read the following line, replace lambda by function in your mind:

>>> f = lambda x: x + 1
>>> f(3)
4

It just defines a function of x. Some other languages, like R, say it explicitly:

> f = function(x) { x + 1 }
> f(3)
4

You see? It’s one of the most natural things to do in programming.


回答 2

两行摘要:

  1. 闭包:非常有用。学习他们,使用他们,爱他们。
  2. Python的lambda关键字:不必要,偶尔有用。如果您发现要使用它进行远程复杂的操作,则将其丢弃并定义一个真正的功能。

The two-line summary:

  1. Closures: Very useful. Learn them, use them, love them.
  2. Python’s lambda keyword: unnecessary, occasionally useful. If you find yourself doing anything remotely complex with it, put it away and define a real function.

回答 3

Lambda是非常重要的抽象机制的一部分,该机制处理高阶函数。为了正确理解其价值,请观看Abelson和Sussman的高质量类,并阅读SICP

这些是现代软件业务中的相关问题,并且变得越来越流行。

A lambda is part of a very important abstraction mechanism which deals with higher order functions. To get proper understanding of its value, please watch high quality lessons from Abelson and Sussman, and read the book SICP

These are relevant issues in modern software business, and becoming ever more popular.


回答 4

lambda在GUI编程中非常有用。例如,假设您要创建一组按钮,并且要使用单个参数化的回调,而不是每个按钮使用唯一的回调。Lambda可让您轻松实现:

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(注意:尽管这个问题是专门询问的lambda,但您也可以使用functools.partial获得相同类型的结果)

另一种方法是为每个按钮创建一个单独的回调,这可能导致代码重复。

lambdas are extremely useful in GUI programming. For example, lets say you’re creating a group of buttons and you want to use a single paramaterized callback rather than a unique callback per button. Lambda lets you accomplish that with ease:

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(Note: although this question is specifically asking about lambda, you can also use functools.partial to get the same type of result)

The alternative is to create a separate callback for each button which can lead to duplicated code.


回答 5

我怀疑lambda会消失。有关最终放弃尝试删除它的信息,请参见Guido的文章。另请参阅冲突概述

您可以查看此帖子,以获得有关Python功能特性背后交易的更多历史记录:http : //python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

奇怪的是,最初促使引入lambda和其他功能特征的map,filter和reduce功能在很大程度上已被列表理解和生成器表达式所取代。实际上,reduce函数已从Python 3.0中的内置函数列表中删除。(但是,没有必要发送有关删除lambda,地图或过滤器的投诉:它们正在留下。:-)

我自己的2美分:就清晰程度而言,lambda很少值得。通常,有一个更清晰的解决方案,其中不包含lambda。

I doubt lambda will go away. See Guido’s post about finally giving up trying to remove it. Also see an outline of the conflict.

You might check out this post for more of a history about the deal behind Python’s functional features: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

Curiously, the map, filter, and reduce functions that originally motivated the introduction of lambda and other functional features have to a large extent been superseded by list comprehensions and generator expressions. In fact, the reduce function was removed from list of builtin functions in Python 3.0. (However, it’s not necessary to send in complaints about the removal of lambda, map or filter: they are staying. :-)

My own two cents: Rarely is lambda worth it as far as clarity goes. Generally there is a more clear solution that doesn’t include lambda.


回答 6

在Python中,lambda这只是内联定义函数的一种方式,

a = lambda x: x + 1
print a(1)

和..

def a(x): return x + 1
print a(1)

..是完全一样的。

使用lambda不能执行任何操作,而使用常规函数则无法执行任何操作-在Python函数中,对象和其他函数一样,都是对象,而lambda只是定义一个函数:

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

老实说,我认为该lambda关键字在Python中是多余的-我从来不需要使用它们(或者看到可以在更适合使用常规函数,列表理解或许多内置函数之一的地方使用)

对于完全随机的示例,请参阅文章“ Python的lambda损坏了!”。

要查看lambda是如何被破坏的,请尝试fs=[f0,...,f9]在其中生成函数列表fi(n)=i+n。第一次尝试:

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

我会争辩说,即使这样做确实可行,这也是可怕的和“非pythonic的”,可以用无数其他方式编写相同的功能,例如:

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

是的,不一样,但是我从未见过需要在列表中生成一组lambda函数的原因。在其他语言中可能也有意义,但是Python不是Haskell(或Lisp或…)

请注意,我们可以使用lambda并仍然以这种方式获得所需的结果:

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

编辑:

在某些情况下,lambda很有用,例如在PyQt应用程序中连接信号时通常很方便,例如:

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

这样做w.textChanged.connect(dothing)只会调用dothing带有额外event参数的方法,并导致错误。使用lambda意味着我们可以整齐地删除参数,而不必定义包装函数。

In Python, lambda is just a way of defining functions inline,

a = lambda x: x + 1
print a(1)

and..

def a(x): return x + 1
print a(1)

..are the exact same.

There is nothing you can do with lambda which you cannot do with a regular function—in Python functions are an object just like anything else, and lambdas simply define a function:

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

I honestly think the lambda keyword is redundant in Python—I have never had the need to use them (or seen one used where a regular function, a list-comprehension or one of the many builtin functions could have been better used instead)

For a completely random example, from the article “Python’s lambda is broken!”:

To see how lambda is broken, try generating a list of functions fs=[f0,...,f9] where fi(n)=i+n. First attempt:

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

I would argue, even if that did work, it’s horribly and “unpythonic”, the same functionality could be written in countless other ways, for example:

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Yes, it’s not the same, but I have never seen a cause where generating a group of lambda functions in a list has been required. It might make sense in other languages, but Python is not Haskell (or Lisp, or …)

Please note that we can use lambda and still achieve the desired results in this way :

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

Edit:

There are a few cases where lambda is useful, for example it’s often convenient when connecting up signals in PyQt applications, like this:

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

Just doing w.textChanged.connect(dothing) would call the dothing method with an extra event argument and cause an error. Using the lambda means we can tidily drop the argument without having to define a wrapping function.


回答 7

我发现lambda对于执行相同功能但对于不同情况的功能列表很有用。

就像Mozilla的复数规则一样

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

如果您必须为所有这些功能定义一个功能,那么到最后它就会让您发疯。
此外,使用函数名称(如plural_rule_1plural_rule_2等)也不是很好。而且eval(),当您依赖于可变函数id时就需要使用它。

I find lambda useful for a list of functions that do the same, but for different circumstances.

Like the Mozilla plural rules:

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

If you’d have to define a function for all of those you’d go mad by the end of it.
Also, it wouldn’t be nice with function names like plural_rule_1, plural_rule_2, etc. And you’d need to eval() it when you’re depending on a variable function id.


回答 8

lambda使用命名函数或列表和生成器表达式,几乎可以做的任何事情都可以做得更好。

因此,在大多数情况下,您基本上只应该是在任何情况下都可以选择的一种(可能不是交互式解释器中编写的草稿代码)。

Pretty much anything you can do with lambda you can do better with either named functions or list and generator expressions.

Consequently, for the most part you should just one of those in basically any situation (except maybe for scratch code written in the interactive interpreter).


回答 9

我已经使用Python几年了,但从未遇到过需要 lambda的情况。确实,如本教程所述,它仅用于语法糖。

I’ve been using Python for a few years and I’ve never run in to a case where I’ve needed lambda. Really, as the tutorial states, it’s just for syntactic sugar.


回答 10

我不能说python的lambda的特定实现,但是总的来说lambda函数确实很方便。它们是函数式编程的核心技术(甚至是THE技术),在面向对象的程序中也很有用。对于某些类型的问题,它们是最好的解决方案,因此绝对不应忘记!

我建议您阅读闭包map函数(链接到python文档,但几乎所有支持功能构造的语言都存在),以了解其有用性。

I can’t speak to python’s particular implementation of lambda, but in general lambda functions are really handy. They’re a core technique (maybe even THE technique) of functional programming, and they’re also very useuful in object-oriented programs. For certain types of problems, they’re the best solution, so certainly shouldn’t be forgotten!

I suggest you read up on closures and the map function (that links to python docs, but it exists in nearly every language that supports functional constructs) to see why it’s useful.


回答 11

Lambda函数是创建函数的非官僚方式。

而已。例如,让我们假设您具有主要功能并且需要对值进行平方。让我们看看传统的方法和lambda方法:

传统方式:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

Lambda方法:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

看到不同?

Lambda函数非常适合列表,例如列表推导或映射。实际上,列表理解是使用lambda表达自己的一种“ pythonic”方式。例如:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

让我们看看语法的每个元素的含义:

[]:“给我一个清单”

x ** 2:“使用此新生函数”

对于a中的x:“放入a中的每个元素”

方便吗?创建这样的功能。让我们使用lambda重写它:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

现在让我们使用地图,这是一回事,但是在语言上是中立的。地图采用2个参数:

(i)一个功能

(ii)可迭代

并为您提供一个列表,其中每个元素都是应用于可迭代元素的函数。

因此,使用map我们将拥有:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

如果您掌握lambda和映射,那么您将拥有以简洁的方式操作数据的强大能力。Lambda函数既不模糊也不使代码清晰。不要将困难与新事物混淆。一旦开始使用它们,您会发现它非常清晰。

Lambda function it’s a non-bureaucratic way to create a function.

That’s it. For example, let’s supose you have your main function and need to square values. Let’s see the traditional way and the lambda way to do this:

Traditional way:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

The lambda way:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

See the difference?

Lambda functions go very well with lists, like lists comprehensions or map. In fact, list comprehension it’s a “pythonic” way to express yourself using lambda. Ex:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

Let’s see what each elements of the syntax means:

[] : “Give me a list”

x**2 : “using this new-born function”

for x in a: “into each element in a”

That’s convenient uh? Creating functions like this. Let’s rewrite it using lambda:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

Now let’s use map, which is the same thing, but more language-neutral. Maps takes 2 arguments:

(i) one function

(ii) an iterable

And gives you a list where each element it’s the function applied to each element of the iterable.

So, using map we would have:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

If you master lambdas and mapping, you will have a great power to manipulate data and in a concise way. Lambda functions are neither obscure nor take away code clarity. Don’t confuse something hard with something new. Once you start using them, you will find it very clear.


回答 12

lambda在我看来,其中的一件好事被低估了,它是将简单形式的评估推迟到需要该值之前的一种方式。让我解释。

实现了许多库例程,以便它们允许某些参数是可调用的(lambda是其中的一个)。想法是,仅在将要使用实际值时(而不是在调用它时)才计算实际值。一个(人为的)示例可能有助于说明这一点。假设您有一个要记录给定时间戳记的例程。您希望例程使用当前时间减去30分钟。你会这样称呼它

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

现在,假设仅当某个事件发生并且您希望仅在该时间计算时间戳时才调用实际函数。你可以这样做

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

假设log_timestampcan可以处理这样的可调用对象,它将在需要时对其进行评估,届时您将获得时间戳。

当然,还有其他方法可以做到这一点(operator例如,使用模块),但我希望我已经传达了这一点。

更新是一个更具体的现实示例。

更新2:我认为这是所谓的“ thunk”的示例。

One of the nice things about lambda that’s in my opinion understated is that it’s way of deferring an evaluation for simple forms till the value is needed. Let me explain.

Many library routines are implemented so that they allow certain parameters to be callables (of whom lambda is one). The idea is that the actual value will be computed only at the time when it’s going to be used (rather that when it’s called). An (contrived) example might help to illustrate the point. Suppose you have a routine which which was going to do log a given timestamp. You want the routine to use the current time minus 30 minutes. You’d call it like so

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

Now suppose the actual function is going to be called only when a certain event occurs and you want the timestamp to be computed only at that time. You can do this like so

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

Assuming the log_timestamp can handle callables like this, it will evaluate this when it needs it and you’ll get the timestamp at that time.

There are of course alternate ways to do this (using the operator module for example) but I hope I’ve conveyed the point.

Update: Here is a slightly more concrete real world example.

Update 2: I think this is an example of what is called a thunk.


回答 13

如上所述,Python中的lambda运算符定义了一个匿名函数,而在Python函数中则是闭包。重要的是不要将闭包的概念与运算符lambda混淆,后者只是语法上的美沙酮。

几年前,当我开始使用Python时,我经常使用lambda,认为它们很酷,而且很理解列表。但是,我编写并必须维护一个用Python编写的大型网站,其功能点约为数千个。我从经验中学到,lambda可以用它们进行原型制作,但是除了保存一些键调用(有时甚至不保存)之外,内联函数(命名为闭包)什么也没有提供。

基本上可以归结为以下几点:

  • 更容易阅读使用有意义的名称明确编写的软件。根据定义,匿名闭包不能具有有意义的名称,因为它们没有名称。出于某种原因,这种简洁似乎也感染了lambda参数,因此我们经常看到像lambda x:x + 1这样的示例
  • 更容易重用已命名的闭包,因为当有名称可以引用时,它们可以多次被名称引用。
  • 调试使用命名闭包而不是lambda的代码更容易,因为该名称将出现在回溯中以及错误周围。

这足以将它们四舍五入并将其转换为命名的闭包。但是,我对匿名关闭持另外两个怨恨。

第一个怨恨就是它们只是使语言混乱的另一个不必要的关键字。

第二个怨恨在范式层次上更深,也就是说,我不喜欢它们提倡一种函数式编程风格,因为这种风格比消息传递,面向对象或过程风格的灵活性差,因为lambda演算不是Turing- complete(幸运的是,在Python中,即使在lambda中,我们仍然可以突破该限制)。我觉得Lambda推广这种风格的原因是:

  • 有一个隐式的回报,即它们似乎“应该”是函数。

  • 它们是另一种更清晰,更易读,更可重用且更通用的机制:方法的状态隐藏机制。

我努力编写无lambda的Python,并删除可见的lambda。我认为如果没有lambda,Python会是一种更好的语言,但这只是我的观点。

As stated above, the lambda operator in Python defines an anonymous function, and in Python functions are closures. It is important not to confuse the concept of closures with the operator lambda, which is merely syntactic methadone for them.

When I started in Python a few years ago, I used lambdas a lot, thinking they were cool, along with list comprehensions. However, I wrote and have to maintain a big website written in Python, with on the order of several thousand function points. I’ve learnt from experience that lambdas might be OK to prototype things with, but offer nothing over inline functions (named closures) except for saving a few key-stokes, or sometimes not.

Basically this boils down to several points:

  • it is easier to read software that is explicitly written using meaningful names. Anonymous closures by definition cannot have a meaningful name, as they have no name. This brevity seems, for some reason, to also infect lambda parameters, hence we often see examples like lambda x: x+1
  • it is easier to reuse named closures, as they can be referred to by name more than once, when there is a name to refer to them by.
  • it is easier to debug code that is using named closures instead of lambdas, because the name will appear in tracebacks, and around the error.

That’s enough reason to round them up and convert them to named closures. However, I hold two other grudges against anonymous closures.

The first grudge is simply that they are just another unnecessary keyword cluttering up the language.

The second grudge is deeper and on the paradigm level, i.e. I do not like that they promote a functional-programming style, because that style is less flexible than the message passing, object oriented or procedural styles, because the lambda calculus is not Turing-complete (luckily in Python, we can still break out of that restriction even inside a lambda). The reasons I feel lambdas promote this style are:

  • There is an implicit return, i.e. they seem like they ‘should’ be functions.

  • They are an alternative state-hiding mechanism to another, more explicit, more readable, more reusable and more general mechanism: methods.

I try hard to write lambda-free Python, and remove lambdas on sight. I think Python would be a slightly better language without lambdas, but that’s just my opinion.


回答 14

Lambda实际上是非常强大的构造,其源于函数式编程的思想,并且在不久的将来Python绝不会轻易对其进行修改,重新定义或删除。它们可以帮助您编写功能更强大的代码,因为它允许您将函数作为参数进行传递,从而使函数成为一流公民。

Lambda的确容易引起混淆,但是一旦获得了扎实的理解,您就可以编写干净的优雅代码,如下所示:

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

上面的代码行返回列表中数字平方的列表。当然,您也可以这样做:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

很明显,以前的代码更短,如果打算仅在一个地方使用map函数(或任何将函数作为参数的类似函数),则尤其如此。这也使代码更加直观和优雅。

另外,正如@David Zaslavsky在他的回答中提到的那样,列表理解并非总是可行的,特别是如果您的列表必须从某种晦涩的数学方法中获取值。

从更实际的角度来看,lambda的最大优点之一对我来说是GUI和事件驱动的编程。如果您看一下Tkinter中的回调,则将它们当作参数的是触发它们的事件。例如

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

现在,如果您要传递一些论点怎么办?只需传递2个参数来存储鼠标单击的坐标即可。您可以像这样轻松地做到这一点:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

现在您可以争辩说可以使用全局变量来完成此操作,但是您是否真的想担心内存管理和泄漏,特别是如果全局变量仅在一个特定的地方使用时呢?那将是糟糕的编程风格。

简而言之,lambda非常棒,绝对不能低估它。尽管Python Lambda与LISP Lambda(功能更强大)不同,但是您确实可以用它们做很多神奇的事情。

Lambdas are actually very powerful constructs that stem from ideas in functional programming, and it is something that by no means will be easily revised, redefined or removed in the near future of Python. They help you write code that is more powerful as it allows you to pass functions as parameters, thus the idea of functions as first-class citizens.

Lambdas do tend to get confusing, but once a solid understanding is obtained, you can write clean elegant code like this:

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

The above line of code returns a list of the squares of the numbers in the list. Ofcourse, you could also do it like:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

It is obvious the former code is shorter, and this is especially true if you intend to use the map function (or any similar function that takes a function as a parameter) in only one place. This also makes the code more intuitive and elegant.

Also, as @David Zaslavsky mentioned in his answer, list comprehensions are not always the way to go especially if your list has to get values from some obscure mathematical way.

From a more practical standpoint, one of the biggest advantages of lambdas for me recently has been in GUI and event-driven programming. If you take a look at callbacks in Tkinter, all they take as arguments are the event that triggered them. E.g.

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

Now what if you had some arguments to pass? Something as simple as passing 2 arguments to store the coordinates of a mouse-click. You can easily do it like this:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

Now you can argue that this can be done using global variables, but do you really want to bang your head worrying about memory management and leakage especially if the global variable will just be used in one particular place? That would be just poor programming style.

In short, lambdas are awesome and should never be underestimated. Python lambdas are not the same as LISP lambdas though (which are more powerful), but you can really do a lot of magical stuff with them.


回答 15

通常,Lambda与函数式编程风格密切相关。您可以通过将函数应用于某些数据并合并结果来解决问题,这是Google用于实现其大多数算法的想法。

以函数式编程风格编写的程序易于并行化,因此在现代多核计算机中变得越来越重要。简而言之,不,您不应该忘记它们。

Lambdas are deeply linked to functional programming style in general. The idea that you can solve problems by applying a function to some data, and merging the results, is what google uses to implement most of its algorithms.

Programs written in functional programming style, are easily parallelized and hence are becoming more and more important with modern multi-core machines. So in short, NO you should not forget them.


回答 16

首先恭喜您找出了lambda。在我看来,这是一个非常强大的构造。如今,趋向于函数式编程语言的趋势无疑表明,既不应该避免也不希望在不久的将来重新定义它。

您只需要稍微有所不同即可。我相信您很快就会喜欢它。但是,如果仅处理python,请小心。因为lambda不是真正的闭包,所以它以某种方式“被破坏了”:pythons lambda被破坏了

First congrats that managed to figure out lambda. In my opinion this is really powerful construct to act with. The trend these days towards functional programming languages is surely an indicator that it neither should be avoided nor it will be redefined in the near future.

You just have to think a little bit different. I’m sure soon you will love it. But be careful if you deal only with python. Because the lambda is not a real closure, it is “broken” somehow: pythons lambda is broken


回答 17

我才刚开始使用Python,然后先进入Lambda,这花了我一段时间才弄清楚。

请注意,这并不是对任何事情的谴责。每个人都有一套不同的事情,这些事情并非易事。

lambda是在现实生活中应该被遗忘的那些“有趣”语言项目之一吗?

没有。

我确定在某些情况下可能需要使用它,但是鉴于它的晦涩之处,

这不是晦涩的。我工作的过去2个团队中,每个人都一直使用此功能。

在将来的版本中重新定义它的潜力(我基于它的各种定义的假设)

除了几年前修复闭包语义外,我还没有认真的提议在Python中重新定义它。

以及降低的编码清晰度-应该避免吗?

如果使用得当,还不清楚。相反,拥有更多可用的语言构造可提高清晰度。

这让我想起了C类型的溢出(缓冲区溢出)-指向顶部变量,并重载了设置其他字段的值。

Lambda就像缓冲区溢出吗?哇。如果您认为这是“维护噩梦”,我无法想象您将如何使用lambda。

I’m just beginning Python and ran head first into Lambda- which took me a while to figure out.

Note that this isn’t a condemnation of anything. Everybody has a different set of things that don’t come easily.

Is lambda one of those ‘interesting’ language items that in real life should be forgotten?

No.

I’m sure there are some edge cases where it might be needed, but given the obscurity of it,

It’s not obscure. The past 2 teams I’ve worked on, everybody used this feature all the time.

the potential of it being redefined in future releases (my assumption based on the various definitions of it)

I’ve seen no serious proposals to redefine it in Python, beyond fixing the closure semantics a few years ago.

and the reduced coding clarity – should it be avoided?

It’s not less clear, if you’re using it right. On the contrary, having more language constructs available increases clarity.

This reminds me of overflowing (buffer overflow) of C types – pointing to the top variable and overloading to set the other field values…sort of a techie showmanship but maintenance coder nightmare..

Lambda is like buffer overflow? Wow. I can’t imagine how you’re using lambda if you think it’s a “maintenance nightmare”.


回答 18

我使用lambda来避免代码重复。它将使函数易于理解,例如:

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

我用临时lambda代替

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)

I use lambdas to avoid code duplication. It would make the function easily comprehensible Eg:

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

I replace that with a temp lambda

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)

回答 19

我今天开始阅读David Mertz的书“ Python中的文本处理”。尽管他对Lambda的描述非常简洁,但结合了附录A中的解释使第一章的示例对我来说(最终)从页面上跳了下来,突然之间我明白了它们的价值。并不是说他的解释对您有用,我仍然处于发现阶段,因此除了以下内容之外,我不会尝试添加其他答复:我是Python新手,还是OOP Lambdas新手。既然我读了Mertz,我想我会得到它们,并且我认为它们非常有用,因为我认为它们允许使用更简洁的编程方法。

他再现了Python的Zen,其中的一句话是简单胜于复杂。作为一个非OOP程序员,使用lambda读取代码(直到上周列出了理解),我曾想过- 这很简单吗?。我今天终于意识到,实际上这些功能使代码比替代方案更具可读性和可理解性,而替代方案始终是某种形式的循环。我还意识到,就像财务报表一样,Python并不是为新手用户设计的,而是为希望受过教育的用户设计的。我不敢相信这种语言有多么强大。当我终于意识到了lambda的目的和价值时,我想撕碎大约30个程序,并在适当的地方重新开始使用lambda。

I started reading David Mertz’s book today ‘Text Processing in Python.’ While he has a fairly terse description of Lambda’s the examples in the first chapter combined with the explanation in Appendix A made them jump off the page for me (finally) and all of a sudden I understood their value. That is not to say his explanation will work for you and I am still at the discovery stage so I will not attempt to add to these responses other than the following: I am new to Python I am new to OOP Lambdas were a struggle for me Now that I read Mertz, I think I get them and I see them as very useful as I think they allow a cleaner approach to programming.

He reproduces the Zen of Python, one line of which is Simple is better than complex. As a non-OOP programmer reading code with lambdas (and until last week list comprehensions) I have thought-This is simple?. I finally realized today that actually these features make the code much more readable, and understandable than the alternative-which is invariably a loop of some sort. I also realized that like financial statements-Python was not designed for the novice user, rather it is designed for the user that wants to get educated. I can’t believe how powerful this language is. When it dawned on me (finally) the purpose and value of lambdas I wanted to rip up about 30 programs and start over putting in lambdas where appropriate.


回答 20

使用lambda的一个有用案例是提高长列表理解的可读性。在此示例中,loop_dic为简洁起见,loop_dic它很短,但可以想象它很长。如果您仅使用包含的纯值i而不是该值的lambda版本,则将获得NameError

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

代替

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

A useful case for using lambdas is to improve the readability of long list comprehensions. In this example loop_dic is short for clarity but imagine loop_dic being very long. If you would just use a plain value that includes i instead of the lambda version of that value you would get a NameError.

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

Instead of

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

回答 21

我可以举一个例子,说明我实际上需要严重的lambda。我正在制作一个图形程序,其中使用权在文件上单击并为其分配三个选项之一。事实证明,在Tkinter(我正在编写的GUI接口程序)中,当有人按下按钮时,无法将其分配给带有参数的命令。因此,如果我选择其中一个选项并希望选择的结果是:

print 'hi there'

那没什么大不了的。但是,如果我需要选择一个特定的细节怎么办?例如,如果我选择选项A,则它调用一个函数,该函数接受依赖于选项A,B或C的某些参数,TKinter不支持此功能。实际上,Lamda是解决此问题的唯一选择。

I can give you an example where I actually needed lambda serious. I’m making a graphical program, where the use right clicks on a file and assigns it one of three options. It turns out that in Tkinter (the GUI interfacing program I’m writing this in), when someone presses a button, it can’t be assigned to a command that takes in arguments. So if I chose one of the options and wanted the result of my choice to be:

print 'hi there'

Then no big deal. But what if I need my choice to have a particular detail. For example, if I choose choice A, it calls a function that takes in some argument that is dependent on the choice A, B or C, TKinter could not support this. Lamda was the only option to get around this actually…


回答 22

我经常使用它,主要是作为空对象或将参数部分绑定到函数。

以下是示例:

实现空对象模式:

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

用于参数绑定:

假设我有以下API

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

然后,当我不想快速将接收到的数据转储到文件时,我可以这样做:

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()

I use it quite often, mainly as a null object or to partially bind parameters to a function.

Here are examples:

to implement null object pattern:

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

for parameter binding:

let say that I have the following API

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

Then, when I wan’t to quickly dump the recieved data to a file I do that:

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()

回答 23

我用 lambda用来创建包含参数的回调。与编写一种执行相同功能的方法相比,在一行中编写一个lambda更加干净。

例如:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

相对于:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb

I use lambda to create callbacks that include parameters. It’s cleaner writing a lambda in one line than to write a method to perform the same functionality.

For example:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

as opposed to:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb

回答 24

我是python的初学者,因此要清楚地了解lambda,我将其与“ for”循环进行了比较;在效率方面。这是代码(python 2.7)-

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)

I’m a python beginner, so to getter a clear idea of lambda I compared it with a ‘for’ loop; in terms of efficiency. Here’s the code (python 2.7) –

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)

回答 25

Lambda是一个过程构造函数。尽管Python的lambda并不是很强大,但是您可以在运行时合成程序。请注意,很少有人了解这种编程。

Lambda is a procedure constructor. You can synthesize programs at run-time, although Python’s lambda is not very powerful. Note that few people understand that kind of programming.


列表理解与lambda +过滤器

问题:列表理解与lambda +过滤器

我碰巧发现自己有一个基本的过滤需求:我有一个列表,并且必须按项目的属性对其进行过滤。

我的代码如下所示:

my_list = [x for x in my_list if x.attribute == value]

但是后来我想,这样写会更好吗?

my_list = filter(lambda x: x.attribute == value, my_list)

它更具可读性,并且如果需要性能,可以将lambda取出以获取收益。

问题是:使用第二种方法是否有警告?有任何性能差异吗?我是否完全想念Pythonic Way™,应该以另一种方式来做到这一点(例如,使用itemgetter而不是lambda)吗?

I happened to find myself having a basic filtering need: I have a list and I have to filter it by an attribute of the items.

My code looked like this:

my_list = [x for x in my_list if x.attribute == value]

But then I thought, wouldn’t it be better to write it like this?

my_list = filter(lambda x: x.attribute == value, my_list)

It’s more readable, and if needed for performance the lambda could be taken out to gain something.

Question is: are there any caveats in using the second way? Any performance difference? Am I missing the Pythonic Way™ entirely and should do it in yet another way (such as using itemgetter instead of the lambda)?


回答 0

奇怪的是,不同的人有多少美丽。我发现列表理解比filter+ 清晰得多lambda,但是请使用任何您更容易理解的列表。

有两件事可能会减慢您对的使用filter

第一个是函数调用开销:使用Python函数(无论是由def还是创建的lambda)后,过滤器的运行速度可能会比列表理解慢。几乎可以肯定,这还不够重要,并且在对代码进行计时并发现它是瓶颈之前,您不应该对性能进行太多的考虑,但是区别仍然存在。

可能适用的其他开销是,lambda被强制访问作用域变量(value)。这比访问局部变量要慢,并且在Python 2.x中,列表推导仅访问局部变量。如果您使用的是Python 3.x,则列表推导是在单独的函数中运行的,因此它也将value通过闭包进行访问,这种区别将不适用。

要考虑的另一个选项是使用生成器而不是列表推导:

def filterbyvalue(seq, value):
   for el in seq:
       if el.attribute==value: yield el

然后,在您的主要代码(这才是真正的可读性)中,您已经用有希望的有意义的函数名称替换了列表理解和过滤器。

It is strange how much beauty varies for different people. I find the list comprehension much clearer than filter+lambda, but use whichever you find easier.

There are two things that may slow down your use of filter.

The first is the function call overhead: as soon as you use a Python function (whether created by def or lambda) it is likely that filter will be slower than the list comprehension. It almost certainly is not enough to matter, and you shouldn’t think much about performance until you’ve timed your code and found it to be a bottleneck, but the difference will be there.

The other overhead that might apply is that the lambda is being forced to access a scoped variable (value). That is slower than accessing a local variable and in Python 2.x the list comprehension only accesses local variables. If you are using Python 3.x the list comprehension runs in a separate function so it will also be accessing value through a closure and this difference won’t apply.

The other option to consider is to use a generator instead of a list comprehension:

def filterbyvalue(seq, value):
   for el in seq:
       if el.attribute==value: yield el

Then in your main code (which is where readability really matters) you’ve replaced both list comprehension and filter with a hopefully meaningful function name.


回答 1

在Python中,这是一个有点宗教性的问题。即使Guido考虑从Python 3中删除它mapfilter并且reduce存在足够的反弹,最终只reduce从内置函数转移到functools.reduce

我个人认为列表理解更容易阅读。[i for i in list if i.attribute == value]由于所有行为都在表面上而不是在过滤器函数内部,因此表达式中发生的事情更加明确。

我不会太担心这两种方法之间的性能差异,因为这是微不足道的。如果确实证明这是您应用程序中的瓶颈(不太可能),我真的只会对其进行优化。

另外,由于BDFL希望filter摆脱这种语言,因此可以肯定地自动使列表理解更具Pythonic ;-)

This is a somewhat religious issue in Python. Even though Guido considered removing map, filter and reduce from Python 3, there was enough of a backlash that in the end only reduce was moved from built-ins to functools.reduce.

Personally I find list comprehensions easier to read. It is more explicit what is happening from the expression [i for i in list if i.attribute == value] as all the behaviour is on the surface not inside the filter function.

I would not worry too much about the performance difference between the two approaches as it is marginal. I would really only optimise this if it proved to be the bottleneck in your application which is unlikely.

Also since the BDFL wanted filter gone from the language then surely that automatically makes list comprehensions more Pythonic ;-)


回答 2

由于任何速度差都将是微不足道的,因此使用过滤器还是列表理解都取决于品味。总的来说,我倾向于使用理解(这里似乎与大多数其他答案一致),但是在某些情况下,我更喜欢使用filter

一个非常常见的用例是抽取某些可迭代的X的值作为谓词P(x):

[x for x in X if P(x)]

但有时您想先将某些函数应用于这些值:

[f(x) for x in X if P(f(x))]


作为一个具体的例子,考虑

primes_cubed = [x*x*x for x in range(1000) if prime(x)]

我认为这看起来比使用略好filter。但是现在考虑

prime_cubes = [x*x*x for x in range(1000) if prime(x*x*x)]

在这种情况下,我们要filter反对后计算值。除了两次计算多维数据集的问题(想象一个更昂贵的计算)外,还有两次写入表达式的问题,这违背了DRY的审美观。在这种情况下,我倾向于使用

prime_cubes = filter(prime, [x*x*x for x in range(1000)])

Since any speed difference is bound to be miniscule, whether to use filters or list comprehensions comes down to a matter of taste. In general I’m inclined to use comprehensions (which seems to agree with most other answers here), but there is one case where I prefer filter.

A very frequent use case is pulling out the values of some iterable X subject to a predicate P(x):

[x for x in X if P(x)]

but sometimes you want to apply some function to the values first:

[f(x) for x in X if P(f(x))]


As a specific example, consider

primes_cubed = [x*x*x for x in range(1000) if prime(x)]

I think this looks slightly better than using filter. But now consider

prime_cubes = [x*x*x for x in range(1000) if prime(x*x*x)]

In this case we want to filter against the post-computed value. Besides the issue of computing the cube twice (imagine a more expensive calculation), there is the issue of writing the expression twice, violating the DRY aesthetic. In this case I’d be apt to use

prime_cubes = filter(prime, [x*x*x for x in range(1000)])

回答 3

尽管filter可能是“更快的方法”,但“ Python方式”将不在乎这些事情,除非性能绝对至关重要(在这种情况下,您将不会使用Python!)。

Although filter may be the “faster way”, the “Pythonic way” would be not to care about such things unless performance is absolutely critical (in which case you wouldn’t be using Python!).


回答 4

我以为我会在python 3中添加,filter()实际上是一个迭代器对象,因此您必须将filter方法调用传递给list()才能构建过滤后的列表。所以在python 2:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = filter(lambda num: num % 2 == 0, lst_a)

列表b和c具有相同的值,并且大约在相同的时间内完成,因为filter()等效[如果在z中,则x表示y中的x]。但是,在3中,相同的代码将使列表c包含过滤器对象,而不是过滤后的列表。要在3中产生相同的值:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = list(filter(lambda num: num %2 == 0, lst_a))

问题在于list()接受一个可迭代的参数,并从该参数创建一个新列表。结果是,在python 3中以这种方式使用filter所花费的时间是[x for x in y if z]中方法的两倍,因为您必须遍历filter()的输出以及原始列表。

I thought I’d just add that in python 3, filter() is actually an iterator object, so you’d have to pass your filter method call to list() in order to build the filtered list. So in python 2:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = filter(lambda num: num % 2 == 0, lst_a)

lists b and c have the same values, and were completed in about the same time as filter() was equivalent [x for x in y if z]. However, in 3, this same code would leave list c containing a filter object, not a filtered list. To produce the same values in 3:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = list(filter(lambda num: num %2 == 0, lst_a))

The problem is that list() takes an iterable as it’s argument, and creates a new list from that argument. The result is that using filter in this way in python 3 takes up to twice as long as the [x for x in y if z] method because you have to iterate over the output from filter() as well as the original list.


回答 5

一个重要的区别是列表理解将list在过滤器返回a 的同时返回filter,而您不能像a那样操作list(即:对其进行调用len,但不能与的返回一起使用filter)。

我自己的自学使我遇到了一些类似的问题。

话虽这么说,如果有一种方法可以list从a中获得结果filter,就像您在.NET中所做的那样lst.Where(i => i.something()).ToList(),我很想知道。

编辑:这是Python 3而不是2的情况(请参阅注释中的讨论)。

An important difference is that list comprehension will return a list while the filter returns a filter, which you cannot manipulate like a list (ie: call len on it, which does not work with the return of filter).

My own self-learning brought me to some similar issue.

That being said, if there is a way to have the resulting list from a filter, a bit like you would do in .NET when you do lst.Where(i => i.something()).ToList(), I am curious to know it.

EDIT: This is the case for Python 3, not 2 (see discussion in comments).


回答 6

我发现第二种方法更具可读性。它确切地告诉您意图是什么:过滤列表。
PS:请勿将“列表”用作变量名

I find the second way more readable. It tells you exactly what the intention is: filter the list.
PS: do not use ‘list’ as a variable name


回答 7

filter如果使用内置函数,通常会稍快一些。

我希望列表理解在您的情况下会更快

generally filter is slightly faster if using a builtin function.

I would expect the list comprehension to be slightly faster in your case


回答 8

过滤器就是这样。它过滤出列表的元素。您可以看到定义中提到的内容相同(在我之前提到的官方文档链接中)。然而,列表理解是什么,作用于后产生一个新的列表的东西前面的列表上。(两个过滤器和列表理解创造了新的名单,并取代旧的名单无法执行操作。这里一个新的名单是像一个列表(例如,一种全新的数据类型。例如将整数转换为字符串等)

在您的示例中,按照定义,使用过滤器比使用列表理解更好。但是,如果您想从列表元素中说other_attribute,在您的示例中要作为新列表进行检索,则可以使用列表理解。

return [item.other_attribute for item in my_list if item.attribute==value]

这就是我实际上记得有关过滤器和列表理解的方式。删除列表中的一些内容并保持其他元素不变,请使用过滤器。在元素上自行使用一些逻辑,并创建适合于某些目的的缩减列表,使用列表理解。

Filter is just that. It filters out the elements of a list. You can see the definition mentions the same(in the official docs link I mentioned before). Whereas, list comprehension is something that produces a new list after acting upon something on the previous list.(Both filter and list comprehension creates new list and not perform operation in place of the older list. A new list here is something like a list with, say, an entirely new data type. Like converting integers to string ,etc)

In your example, it is better to use filter than list comprehension, as per the definition. However, if you want, say other_attribute from the list elements, in your example is to be retrieved as a new list, then you can use list comprehension.

return [item.other_attribute for item in my_list if item.attribute==value]

This is how I actually remember about filter and list comprehension. Remove a few things within a list and keep the other elements intact, use filter. Use some logic on your own at the elements and create a watered down list suitable for some purpose, use list comprehension.


回答 9

这是我需要在列表理解进行筛选时使用的一小段内容。只是过滤器,lambda和列表(也称为猫的忠诚度和狗的清洁度)的组合。

在这种情况下,我正在读取文件,删除空白行,注释掉行,以及对行进行注释后的所有内容:

# Throw out blank lines and comments
with open('file.txt', 'r') as lines:        
    # From the inside out:
    #    [s.partition('#')[0].strip() for s in lines]... Throws out comments
    #   filter(lambda x: x!= '', [s.part... Filters out blank lines
    #  y for y in filter... Converts filter object to list
    file_contents = [y for y in filter(lambda x: x != '', [s.partition('#')[0].strip() for s in lines])]

Here’s a short piece I use when I need to filter on something after the list comprehension. Just a combination of filter, lambda, and lists (otherwise known as the loyalty of a cat and the cleanliness of a dog).

In this case I’m reading a file, stripping out blank lines, commented out lines, and anything after a comment on a line:

# Throw out blank lines and comments
with open('file.txt', 'r') as lines:        
    # From the inside out:
    #    [s.partition('#')[0].strip() for s in lines]... Throws out comments
    #   filter(lambda x: x!= '', [s.part... Filters out blank lines
    #  y for y in filter... Converts filter object to list
    file_contents = [y for y in filter(lambda x: x != '', [s.partition('#')[0].strip() for s in lines])]

回答 10

除了可接受的答案外,还有一个极端的情况,您应该使用过滤器而不是列表推导。如果列表不可散列,则无法直接使用列表推导处理它。一个真实的例子是,如果您用来pyodbc从数据库中读取结果。在fetchAll()从结果cursor是unhashable列表。在这种情况下,要直接处理返回的结果,应使用过滤器:

cursor.execute("SELECT * FROM TABLE1;")
data_from_db = cursor.fetchall()
processed_data = filter(lambda s: 'abc' in s.field1 or s.StartTime >= start_date_time, data_from_db) 

如果您在此处使用列表理解,则会出现错误:

TypeError:无法散列的类型:“列表”

In addition to the accepted answer, there is a corner case when you should use filter instead of a list comprehension. If the list is unhashable you cannot directly process it with a list comprehension. A real world example is if you use pyodbc to read results from a database. The fetchAll() results from cursor is an unhashable list. In this situation, to directly manipulating on the returned results, filter should be used:

cursor.execute("SELECT * FROM TABLE1;")
data_from_db = cursor.fetchall()
processed_data = filter(lambda s: 'abc' in s.field1 or s.StartTime >= start_date_time, data_from_db) 

If you use list comprehension here you will get the error:

TypeError: unhashable type: ‘list’


回答 11

我花了一些时间熟悉higher order functions filterand map。因此,我习惯了它们,实际上我很喜欢filter,因为很明显它通过保留真实内容来进行过滤,而且我知道一些functional programming术语也很酷。

然后,我读了这段文章(Fluent Python书):

map和filter函数仍是Python 3中的内置函数,但是由于引入了列表理解和生成器表达式,因此它们并不那么重要。listcomp或genexp可将地图和过滤器组合在一起,但可读性更高。

现在,我想,如果您可以使用已经很广泛的成语(例如列表理解)来实现filter/ 的概念,那又何必困扰 map呢?而且mapsfilters是种功能。在这种情况下,我更喜欢使用Anonymous functionslambda。

最后,仅出于测试目的,我对这两种方法(maplistComp)都进行了计时,但没有看到任何相关的速度差异来证明对此进行论证的合理性。

from timeit import Timer

timeMap = Timer(lambda: list(map(lambda x: x*x, range(10**7))))
print(timeMap.timeit(number=100))

timeListComp = Timer(lambda:[(lambda x: x*x) for x in range(10**7)])
print(timeListComp.timeit(number=100))

#Map:                 166.95695265199174
#List Comprehension   177.97208347299602

It took me some time to get familiarized with the higher order functions filter and map. So i got used to them and i actually liked filter as it was explicit that it filters by keeping whatever is truthy and I’ve felt cool that I knew some functional programming terms.

Then I read this passage (Fluent Python Book):

The map and filter functions are still builtins in Python 3, but since the introduction of list comprehensions and generator ex‐ pressions, they are not as important. A listcomp or a genexp does the job of map and filter combined, but is more readable.

And now I think, why bother with the concept of filter / map if you can achieve it with already widely spread idioms like list comprehensions. Furthermore maps and filters are kind of functions. In this case I prefer using Anonymous functions lambdas.

Finally, just for the sake of having it tested, I’ve timed both methods (map and listComp) and I didn’t see any relevant speed difference that would justify making arguments about it.

from timeit import Timer

timeMap = Timer(lambda: list(map(lambda x: x*x, range(10**7))))
print(timeMap.timeit(number=100))

timeListComp = Timer(lambda:[(lambda x: x*x) for x in range(10**7)])
print(timeListComp.timeit(number=100))

#Map:                 166.95695265199174
#List Comprehension   177.97208347299602

回答 12

奇怪的是,在Python 3上,我看到过滤器的执行速度快于列表推导。

我一直认为列表理解会更有效。类似于:[如果名称不是None,则在brand_names_db中使用名称命名]生成的字节码要好一些。

>>> def f1(seq):
...     return list(filter(None, seq))
>>> def f2(seq):
...     return [i for i in seq if i is not None]
>>> disassemble(f1.__code__)
2         0 LOAD_GLOBAL              0 (list)
          2 LOAD_GLOBAL              1 (filter)
          4 LOAD_CONST               0 (None)
          6 LOAD_FAST                0 (seq)
          8 CALL_FUNCTION            2
         10 CALL_FUNCTION            1
         12 RETURN_VALUE
>>> disassemble(f2.__code__)
2           0 LOAD_CONST               1 (<code object <listcomp> at 0x10cfcaa50, file "<stdin>", line 2>)
          2 LOAD_CONST               2 ('f2.<locals>.<listcomp>')
          4 MAKE_FUNCTION            0
          6 LOAD_FAST                0 (seq)
          8 GET_ITER
         10 CALL_FUNCTION            1
         12 RETURN_VALUE

但是它们实际上要慢一些:

   >>> timeit(stmt="f1(range(1000))", setup="from __main__ import f1,f2")
   21.177661532000116
   >>> timeit(stmt="f2(range(1000))", setup="from __main__ import f1,f2")
   42.233950221000214

Curiously on Python 3, I see filter performing faster than list comprehensions.

I always thought that the list comprehensions would be more performant. Something like: [name for name in brand_names_db if name is not None] The bytecode generated is a bit better.

>>> def f1(seq):
...     return list(filter(None, seq))
>>> def f2(seq):
...     return [i for i in seq if i is not None]
>>> disassemble(f1.__code__)
2         0 LOAD_GLOBAL              0 (list)
          2 LOAD_GLOBAL              1 (filter)
          4 LOAD_CONST               0 (None)
          6 LOAD_FAST                0 (seq)
          8 CALL_FUNCTION            2
         10 CALL_FUNCTION            1
         12 RETURN_VALUE
>>> disassemble(f2.__code__)
2           0 LOAD_CONST               1 (<code object <listcomp> at 0x10cfcaa50, file "<stdin>", line 2>)
          2 LOAD_CONST               2 ('f2.<locals>.<listcomp>')
          4 MAKE_FUNCTION            0
          6 LOAD_FAST                0 (seq)
          8 GET_ITER
         10 CALL_FUNCTION            1
         12 RETURN_VALUE

But they are actually slower:

   >>> timeit(stmt="f1(range(1000))", setup="from __main__ import f1,f2")
   21.177661532000116
   >>> timeit(stmt="f2(range(1000))", setup="from __main__ import f1,f2")
   42.233950221000214

回答 13

我拿

def filter_list(list, key, value, limit=None):
    return [i for i in list if i[key] == value][:limit]

My take

def filter_list(list, key, value, limit=None):
    return [i for i in list if i[key] == value][:limit]