标签归档:lambda

Python中Lambda表达式内的赋值

问题:Python中Lambda表达式内的赋值

我有一个对象列表,我想使用filterlambda表达式删除除一个以外的所有空对象。

例如,如果输入是:

[Object(name=""), Object(name="fake_name"), Object(name="")]

…那么输出应为:

[Object(name=""), Object(name="fake_name")]

有没有一种方法可以向lambda表达式添加赋值?例如:

flag = True 
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(
    (lambda o: [flag or bool(o.name), flag = flag and bool(o.name)][0]),
    input
)

I have a list of objects and I want to remove all objects that are empty except for one, using filter and a lambda expression.

For example if the input is:

[Object(name=""), Object(name="fake_name"), Object(name="")]

…then the output should be:

[Object(name=""), Object(name="fake_name")]

Is there a way to add an assignment to a lambda expression? For example:

flag = True 
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(
    (lambda o: [flag or bool(o.name), flag = flag and bool(o.name)][0]),
    input
)

回答 0

:=Python 3.8中添加的赋值表达式运算符支持lambda表达式内部的赋值。出于语法原因,此运算符只能出现在括号(...),括号[...]或括号中{...}。例如,我们将能够编写以下内容:

import sys
say_hello = lambda: (
    message := "Hello world",
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

在Python 2中,可以执行本地分配作为列表理解的副作用。

import sys
say_hello = lambda: (
    [None for message in ["Hello world"]],
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

但是,由于您的变量flag位于外部作用域而不是的作用域中,因此在您的示例中无法使用这两个方法lambda。这与无关lambda,这是Python 2中的常规行为。Python3可让您nonlocaldefs 内使用关键字解决此问题,但nonlocal不能在lambdas 内使用。

有一种解决方法(请参阅下文),但是当我们讨论该主题时…


在某些情况下,您可以使用它来执行a内部的所有操作lambda

(lambda: [
    ['def'
        for sys in [__import__('sys')]
        for math in [__import__('math')]

        for sub in [lambda *vals: None]
        for fun in [lambda *vals: vals[-1]]

        for echo in [lambda *vals: sub(
            sys.stdout.write(u" ".join(map(unicode, vals)) + u"\n"))]

        for Cylinder in [type('Cylinder', (object,), dict(
            __init__ = lambda self, radius, height: sub(
                setattr(self, 'radius', radius),
                setattr(self, 'height', height)),

            volume = property(lambda self: fun(
                ['def' for top_area in [math.pi * self.radius ** 2]],

                self.height * top_area))))]

        for main in [lambda: sub(
            ['loop' for factor in [1, 2, 3] if sub(
                ['def'
                    for my_radius, my_height in [[10 * factor, 20 * factor]]
                    for my_cylinder in [Cylinder(my_radius, my_height)]],

                echo(u"A cylinder with a radius of %.1fcm and a height "
                     u"of %.1fcm has a volume of %.1fcm³."
                     % (my_radius, my_height, my_cylinder.volume)))])]],

    main()])()

半径为10.0cm,高度为20.0cm的圆柱体的容积为6283.2cm³。
半径为20.0cm,高度为40.0cm的圆柱体的容积为50265.5cm³。
半径为30.0cm,高度为60.0cm的圆柱体的体积为169646.0cm³。

请不要。


…回到您的原始示例:尽管您无法flag在外部范围内对变量进行赋值,但可以使用函数来修改先前分配的值。

例如,flag可以是.value我们使用设置的对象setattr

flag = Object(value=True)
input = [Object(name=''), Object(name='fake_name'), Object(name='')] 
output = filter(lambda o: [
    flag.value or bool(o.name),
    setattr(flag, 'value', flag.value and bool(o.name))
][0], input)
[Object(name=''), Object(name='fake_name')]

如果我们想适合上述主题,可以使用列表推导代替setattr

    [None for flag.value in [bool(o.name)]]

但是实际上,在严肃的代码中,lambda如果要进行外部分配,则应始终使用常规函数定义而不是a 。

flag = Object(value=True)
def not_empty_except_first(o):
    result = flag.value or bool(o.name)
    flag.value = flag.value and bool(o.name)
    return result
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(not_empty_except_first, input)

The assignment expression operator := added in Python 3.8 supports assignment inside of lambda expressions. This operator can only appear within a parenthesized (...), bracketed [...], or braced {...} expression for syntactic reasons. For example, we will be able to write the following:

import sys
say_hello = lambda: (
    message := "Hello world",
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

In Python 2, it was possible to perform local assignments as a side effect of list comprehensions.

import sys
say_hello = lambda: (
    [None for message in ["Hello world"]],
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

However, it’s not possible to use either of these in your example because your variable flag is in an outer scope, not the lambda‘s scope. This doesn’t have to do with lambda, it’s the general behaviour in Python 2. Python 3 lets you get around this with the nonlocal keyword inside of defs, but nonlocal can’t be used inside lambdas.

There’s a workaround (see below), but while we’re on the topic…


In some cases you can use this to do everything inside of a lambda:

(lambda: [
    ['def'
        for sys in [__import__('sys')]
        for math in [__import__('math')]

        for sub in [lambda *vals: None]
        for fun in [lambda *vals: vals[-1]]

        for echo in [lambda *vals: sub(
            sys.stdout.write(u" ".join(map(unicode, vals)) + u"\n"))]

        for Cylinder in [type('Cylinder', (object,), dict(
            __init__ = lambda self, radius, height: sub(
                setattr(self, 'radius', radius),
                setattr(self, 'height', height)),

            volume = property(lambda self: fun(
                ['def' for top_area in [math.pi * self.radius ** 2]],

                self.height * top_area))))]

        for main in [lambda: sub(
            ['loop' for factor in [1, 2, 3] if sub(
                ['def'
                    for my_radius, my_height in [[10 * factor, 20 * factor]]
                    for my_cylinder in [Cylinder(my_radius, my_height)]],

                echo(u"A cylinder with a radius of %.1fcm and a height "
                     u"of %.1fcm has a volume of %.1fcm³."
                     % (my_radius, my_height, my_cylinder.volume)))])]],

    main()])()

A cylinder with a radius of 10.0cm and a height of 20.0cm has a volume of 6283.2cm³.
A cylinder with a radius of 20.0cm and a height of 40.0cm has a volume of 50265.5cm³.
A cylinder with a radius of 30.0cm and a height of 60.0cm has a volume of 169646.0cm³.

Please don’t.


…back to your original example: though you can’t perform assignments to the flag variable in the outer scope, you can use functions to modify the previously-assigned value.

For example, flag could be an object whose .value we set using setattr:

flag = Object(value=True)
input = [Object(name=''), Object(name='fake_name'), Object(name='')] 
output = filter(lambda o: [
    flag.value or bool(o.name),
    setattr(flag, 'value', flag.value and bool(o.name))
][0], input)
[Object(name=''), Object(name='fake_name')]

If we wanted to fit the above theme, we could use a list comprehension instead of setattr:

    [None for flag.value in [bool(o.name)]]

But really, in serious code you should always use a regular function definition instead of a lambda if you’re going to be doing outer assignment.

flag = Object(value=True)
def not_empty_except_first(o):
    result = flag.value or bool(o.name)
    flag.value = flag.value and bool(o.name)
    return result
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(not_empty_except_first, input)

回答 1

您不能真正维护filter/ lambda表达式中的状态(除非滥用全局命名空间)。但是,您可以使用在reduce()表达式中传递的累加结果来实现类似的目的:

>>> f = lambda a, b: (a.append(b) or a) if (b not in a) else a
>>> input = ["foo", u"", "bar", "", "", "x"]
>>> reduce(f, input, [])
['foo', u'', 'bar', 'x']
>>> 

当然,您可以稍微调整一下条件。在这种情况下,它会过滤出重复项,但是您也可以使用a.count(""),例如,仅限制空字符串。

不用说,您可以执行此操作,但实际上不应该这样做。:)

最后,您可以在纯Python中执行任何操作lambdahttp : //vanderwijk.info/blog/pure-lambda-calculus-python/

You cannot really maintain state in a filter/lambda expression (unless abusing the global namespace). You can however achieve something similar using the accumulated result being passed around in a reduce() expression:

>>> f = lambda a, b: (a.append(b) or a) if (b not in a) else a
>>> input = ["foo", u"", "bar", "", "", "x"]
>>> reduce(f, input, [])
['foo', u'', 'bar', 'x']
>>> 

You can, of course, tweak the condition a bit. In this case it filters out duplicates, but you can also use a.count(""), for example, to only restrict empty strings.

Needless to say, you can do this but you really shouldn’t. :)

Lastly, you can do anything in pure Python lambda: http://vanderwijk.info/blog/pure-lambda-calculus-python/


回答 2

当您可以删除所有空值并在输入大小更改时放回一个值时,就无需使用lambda :

input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = [x for x in input if x.name]
if(len(input) != len(output)):
    output.append(Object(name=""))

There’s no need to use a lambda, when you can remove all the null ones, and put one back if the input size changes:

input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = [x for x in input if x.name]
if(len(input) != len(output)):
    output.append(Object(name=""))

回答 3

尽管可以与和朋友一起执行各种技巧,但表达式=内部不可能进行普通赋值()。 lambdasetattr

但是,解决您的问题实际上非常简单:

input = [Object(name=""), Object(name="fake_name"), Object(name="")]
output = filter(
    lambda o, _seen=set():
        not (not o and o in _seen or _seen.add(o)),
    input
    )

这会给你

[Object(Object(name=''), name='fake_name')]

如您所见,它将保留第一个空白实例,而不是最后一个。如果您需要最后一个,则将进入filter的列表反向,然后反转来自的列表filter

output = filter(
    lambda o, _seen=set():
        not (not o and o in _seen or _seen.add(o)),
    input[::-1]
    )[::-1]

这会给你

[Object(name='fake_name'), Object(name='')]

有一点要注意的:为了让这个与任意对象的工作,这些对象必须正确贯彻__eq____hash__作为解释在这里

Normal assignment (=) is not possible inside a lambda expression, although it is possible to perform various tricks with setattr and friends.

Solving your problem, however, is actually quite simple:

input = [Object(name=""), Object(name="fake_name"), Object(name="")]
output = filter(
    lambda o, _seen=set():
        not (not o and o in _seen or _seen.add(o)),
    input
    )

which will give you

[Object(Object(name=''), name='fake_name')]

As you can see, it’s keeping the first blank instance instead of the last. If you need the last instead, reverse the list going in to filter, and reverse the list coming out of filter:

output = filter(
    lambda o, _seen=set():
        not (not o and o in _seen or _seen.add(o)),
    input[::-1]
    )[::-1]

which will give you

[Object(name='fake_name'), Object(name='')]

One thing to be aware of: in order for this to work with arbitrary objects, those objects must properly implement __eq__ and __hash__ as explained here.


回答 4

更新

[o for d in [{}] for o in lst if o.name != "" or d.setdefault("", o) == o]

或使用filterlambda

flag = {}
filter(lambda o: bool(o.name) or flag.setdefault("", o) == o, lst)

上一个答案

好的,您是否坚持使用filter和lambda?

似乎通过字典理解会更好,

{o.name : o for o in input}.values()

我认为Python不允许在lambda中进行赋值的原因与为什么它在理解中不允许进行赋值的原因相似,这与以下事实有关:这些东西都是在C一边评估的,因此可以给我们一个增加速度。至少那是看完Guido的一篇文章后给我的印象。

我的猜测是,这也将违背其哲学一个在Python做任何一件事情的正确方法。

UPDATE:

[o for d in [{}] for o in lst if o.name != "" or d.setdefault("", o) == o]

or using filter and lambda:

flag = {}
filter(lambda o: bool(o.name) or flag.setdefault("", o) == o, lst)

Previous Answer

OK, are you stuck on using filter and lambda?

It seems like this would be better served with a dictionary comprehension,

{o.name : o for o in input}.values()

I think the reason that Python doesn’t allow assignment in a lambda is similar to why it doesn’t allow assignment in a comprehension and that’s got something to do with the fact that these things are evaluated on the C side and thus can give us an increase in speed. At least that’s my impression after reading one of Guido’s essays.

My guess is this would also go against the philosophy of having one right way of doing any one thing in Python.


回答 5

TL; DR:使用功能惯用法时,最好编写功能代码

正如许多人指出的那样,在Python中不允许进行lambda赋值。通常,在使用功能性习惯用法时,您最好以功能性方式进行思考,这意味着在没有副作用的情况下也没有赋值。

这是使用lambda的功能解决方案。fn为了清楚起见,我将lambda分配给了它(并且因为它有点长)。

from operator import add
from itertools import ifilter, ifilterfalse
fn = lambda l, pred: add(list(ifilter(pred, iter(l))), [ifilterfalse(pred, iter(l)).next()])
objs = [Object(name=""), Object(name="fake_name"), Object(name="")]
fn(objs, lambda o: o.name != '')

您也可以通过稍微改变一些东西来处理迭代器而不是列表。您也有一些不同的进口。

from itertools import chain, islice, ifilter, ifilterfalse
fn = lambda l, pred: chain(ifilter(pred, iter(l)), islice(ifilterfalse(pred, iter(l)), 1))

您始终可以重新组织代码以减少语句的长度。

TL;DR: When using functional idioms it’s better to write functional code

As many people have pointed out, in Python lambdas assignment is not allowed. In general when using functional idioms your better off thinking in a functional manner which means wherever possible no side effects and no assignments.

Here is functional solution which uses a lambda. I’ve assigned the lambda to fn for clarity (and because it got a little long-ish).

from operator import add
from itertools import ifilter, ifilterfalse
fn = lambda l, pred: add(list(ifilter(pred, iter(l))), [ifilterfalse(pred, iter(l)).next()])
objs = [Object(name=""), Object(name="fake_name"), Object(name="")]
fn(objs, lambda o: o.name != '')

You can also make this deal with iterators rather than lists by changing things around a little. You also have some different imports.

from itertools import chain, islice, ifilter, ifilterfalse
fn = lambda l, pred: chain(ifilter(pred, iter(l)), islice(ifilterfalse(pred, iter(l)), 1))

You can always reoganize the code to reduce the length of the statements.


回答 6

如果代替flag = True我们可以代替导入,那么我认为这符合标准:

>>> from itertools import count
>>> a = ['hello', '', 'world', '', '', '', 'bob']
>>> filter(lambda L, j=count(): L or not next(j), a)
['hello', '', 'world', 'bob']

或者,过滤器最好写成:

>>> filter(lambda L, blank_count=count(1): L or next(blank_count) == 1, a)

或者,仅是一个简单的布尔值,没有任何导入:

filter(lambda L, use_blank=iter([True]): L or next(use_blank, False), a)

If instead of flag = True we can do an import instead, then I think this meets the criteria:

>>> from itertools import count
>>> a = ['hello', '', 'world', '', '', '', 'bob']
>>> filter(lambda L, j=count(): L or not next(j), a)
['hello', '', 'world', 'bob']

Or maybe the filter is better written as:

>>> filter(lambda L, blank_count=count(1): L or next(blank_count) == 1, a)

Or, just for a simple boolean, without any imports:

filter(lambda L, use_blank=iter([True]): L or next(use_blank, False), a)

回答 7

在迭代过程中跟踪状态的Python方法是使用生成器。itertools的方法很难理解恕我直言,而试图破解lambda来做到这一点显然是愚蠢的。我会尝试:

def keep_last_empty(input):
    last = None
    for item in iter(input):
        if item.name: yield item
        else: last = item
    if last is not None: yield last

output = list(keep_last_empty(input))

总体而言,可读性每次都比紧凑性好。

The pythonic way to track state during iteration is with generators. The itertools way is quite hard to understand IMHO and trying to hack lambdas to do this is plain silly. I’d try:

def keep_last_empty(input):
    last = None
    for item in iter(input):
        if item.name: yield item
        else: last = item
    if last is not None: yield last

output = list(keep_last_empty(input))

Overall, readability trumps compactness every time.


回答 8

不可以,由于其自​​身的定义,您无法将分配放入lambda中。如果使用函数式编程进行工作,则必须假定您的值不可更改。

一种解决方案是以下代码:

output = lambda l, name: [] if l==[] \
             else [ l[ 0 ] ] + output( l[1:], name ) if l[ 0 ].name == name \
             else output( l[1:], name ) if l[ 0 ].name == "" \
             else [ l[ 0 ] ] + output( l[1:], name )

No, you cannot put an assignment inside a lambda because of its own definition. If you work using functional programming, then you must assume that your values are not mutable.

One solution would be the following code:

output = lambda l, name: [] if l==[] \
             else [ l[ 0 ] ] + output( l[1:], name ) if l[ 0 ].name == name \
             else output( l[1:], name ) if l[ 0 ].name == "" \
             else [ l[ 0 ] ] + output( l[1:], name )

回答 9

如果您需要一个lambda来记住调用之间的状态,则建议您在本地命名空间中声明的函数或带有重载的类 __call__。既然我对您要执行的操作的所有警告都已解决,我们可以为您的查询提供实际答案。

如果确实需要让lambda在两次调用之间有一些内存,则可以将其定义为:

f = lambda o, ns = {"flag":True}: [ns["flag"] or o.name, ns.__setitem__("flag", ns["flag"] and o.name)][0]

然后,您只需传递f给即可filter()。如果确实需要,您可以找回价值flag使用以下方法:

f.__defaults__[0]["flag"]

或者,您可以通过修改的结果来修改全局命名空间globals()。不幸的是,您不能以与修改结果locals()不会影响本地命名空间相同的方式来修改本地命名空间。

If you need a lambda to remember state between calls, I would recommend either a function declared in the local namespace or a class with an overloaded __call__. Now that all my cautions against what you are trying to do is out of the way, we can get to an actual answer to your query.

If you really need to have your lambda to have some memory between calls, you can define it like:

f = lambda o, ns = {"flag":True}: [ns["flag"] or o.name, ns.__setitem__("flag", ns["flag"] and o.name)][0]

Then you just need to pass f to filter(). If you really need to, you can get back the value of flag with the following:

f.__defaults__[0]["flag"]

Alternatively, you can modify the global namespace by modifying the result of globals(). Unfortunately, you cannot modify the local namespace in the same way as modifying the result of locals() doesn’t affect the local namespace.


回答 10

您可以使用绑定函数来使用伪多语句lambda。然后,您可以将包装器类用于Flag以启用分配。

bind = lambda x, f=(lambda y: y): f(x)

class Flag(object):
    def __init__(self, value):
        self.value = value

    def set(self, value):
        self.value = value
        return value

input = [Object(name=""), Object(name="fake_name"), Object(name="")]
flag = Flag(True)
output = filter(
            lambda o: (
                bind(flag.value, lambda orig_flag_value:
                bind(flag.set(flag.value and bool(o.name)), lambda _:
                bind(orig_flag_value or bool(o.name))))),
            input)

You can use a bind function to use a pseudo multi-statement lambda. Then you can use a wrapper class for a Flag to enable assignment.

bind = lambda x, f=(lambda y: y): f(x)

class Flag(object):
    def __init__(self, value):
        self.value = value

    def set(self, value):
        self.value = value
        return value

input = [Object(name=""), Object(name="fake_name"), Object(name="")]
flag = Flag(True)
output = filter(
            lambda o: (
                bind(flag.value, lambda orig_flag_value:
                bind(flag.set(flag.value and bool(o.name)), lambda _:
                bind(orig_flag_value or bool(o.name))))),
            input)

回答 11

有点麻烦的解决方法,但是在lambda中进行分配无论如何都是非法的,因此这并不重要。您可以使用内置exec()函数从lambda内部运行分配,例如以下示例:

>>> val
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    val
NameError: name 'val' is not defined
>>> d = lambda: exec('val=True', globals())
>>> d()
>>> val
True

Kind of a messy workaround, but assignment in lambdas is illegal anyway, so it doesn’t really matter. You can use the builtin exec() function to run assignment from inside the lambda, such as this example:

>>> val
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    val
NameError: name 'val' is not defined
>>> d = lambda: exec('val=True', globals())
>>> d()
>>> val
True

回答 12

首先,您不需要为工作使用本地服务,只需检查以上答案

其次,使用locals()和globals()来获取变量表,然后更改值很简单

检查以下示例代码:

print [locals().__setitem__('x', 'Hillo :]'), x][-1]

如果您需要更改将全局变量添加到您的环境,请尝试将locals()替换为globals()

python的list comp很酷,但是大多数triditional项目不接受此命令(例如flask:[)

希望它可以帮助

first , you dont need to use a local assigment for your job, just check the above answer

second, its simple to use locals() and globals() to got the variables table and then change the value

check this sample code:

print [locals().__setitem__('x', 'Hillo :]'), x][-1]

if you need to change the add a global variable to your environ, try to replace locals() with globals()

python’s list comp is cool but most of the triditional project dont accept this(like flask :[)

hope it could help


使用哪个更合适:lambda函数或嵌套函数(’def’)?

问题:使用哪个更合适:lambda函数或嵌套函数(’def’)?

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

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

Lambda函数

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

嵌套功能

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

>>> b(5)
6

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

有关系吗 如果不这样做,那确实违反了Python原则:

应该有一种(最好只有一种)明显的方式来做到这一点

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

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

Lambda function

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

Nested function

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

>>> b(5)
6

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

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

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


回答 0

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

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

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

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

对于情况下,你真的需要一个小的函数对象,你应该使用operator模块的功能,如operator.add代替lambda x, y: x + y

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

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

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

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

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

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

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

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

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


回答 1

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

首先是关于他们做什么以及他们返回什么:

  • def是不返回任何内容并在本地命名空间中创建“名称”的关键字。

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

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

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

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

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

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

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

例如,

def p(x): print x

如预期般运作

lambda x: print x

是一个SyntaxError。

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

Practically speaking, to me there are two differences:

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

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

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

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

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

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

is quite common, and more concise with lambdas.

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

  • A function defined with ‘def’ can contain any python code
  • A function defined with ‘lambda’ has to evaluate to an expression, and can thus not contain statements like print, import, raise, …

For example,

def p(x): print x

works as expected, while

lambda x: print x

is a SyntaxError.

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


回答 2

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

问:您最不满意Python的什么功能?

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

在实践中,结果并非如此。Python只有两个范围:本地和全局。这使编写lambda函数很痛苦,因为您经常想在lambda定义的作用域中访问变量,但由于这两个作用域而不能。有办法解决这个问题,但这有点不合时宜。在Python中,通常只使用for循环而不是搞乱lambda函数似乎容易得多。只有当已有内置功能可以满足您的需求时,地图和朋友才能正常工作。

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

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

我写了它,花了我一分钟才弄清楚。这是来自欧拉计划-我不会说哪个问题,因为我讨厌剧透,但是它只需要0.124秒即可:)

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

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

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

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

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

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

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


回答 3

对于n = 1000,这是调用函数与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

For n=1000 here’s some timeit’s of calling a function vs a 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

回答 4

性能:

创建一个功能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)

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


Python原则:“应该有一种-最好只有一种-显而易见的方法”

这类似于真理教义的单一来源。不幸的是,单行之道的原则一直是Python的渴望,而不是真正的指导原则。考虑一下Python中非常强大的数组理解。它们在功能上等效于mapfilter函数:

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

lambdadef一样。

这是一个见解,但是我想说,Python语言中用于一般用途的任何东西如果没有明显破坏任何东西,都足够“ Pythonic”。

Performance:

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


Readability:

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

# Using non-functional version.

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

# Using lambda with functional version.

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

# Using def with functional version.

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

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

deal_with_headings(v, size, direction)

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


Limitations:

  • lambda functions can only be used once, unless assigned to a variable name.
  • lambda functions assigned to variable names have no advantage over def functions.
  • lambda functions can be difficult or impossible to pickle.
  • def functions’ names must be carefully chosen to be reasonably descriptive and unique or at least otherwise unused in scope.

Consistency:

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


Pre-existing functions:

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

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

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


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

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

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

lambda and def are the same.

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


回答 5

更可取的是:lambda函数还是嵌套函数(def)?

与常规函数相比,使用lambda有一个优点:它们是在表达式中创建的。

有几个缺点:

  • 没有名字(只是'<lambda>'
  • 没有文档字符串
  • 没有注释
  • 没有复杂的陈述

它们也是相同类型的对象。由于这些原因,我通常更喜欢使用def关键字而不是lambdas 创建函数。

要点-它们是同一类型的对象

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缺少某些功能,这些功能是通过完整的函数定义语法获得的。

兰巴舞__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具有文档:

>>> 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,因此可以在函数调用内部创建它。

与在其他位置创建的名称相比,在函数调用内部创建一个函数可以避免(廉价的)名称查找。

但是,由于严格评估了Python,因此除了避免名称查找外,这样做没有其他性能上的提高。

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

在做交互式Python时,我也倾向于使用lambdas,以避免在可能的情况下出现多行。当我想在调用时将参数传递给构造函数时,我使用以下代码格式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代替with 来创建函数lambda

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

There is one advantage to using a lambda over a regular function: they are created in an expression.

There are several drawbacks:

  • no name (just '<lambda>')
  • no docstrings
  • no annotations
  • no complex statements

They are also both the same type of object. For those reasons, I generally prefer to create functions with the def keyword instead of with lambdas.

First point – they’re the same type of object

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

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

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

Both lambdas and functions:

  • can be passed around as an argument (same as a regular function)
  • when created within an outer function become a closure over that outer functions’ locals

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

A lamba’s __name__ is '<lambda>'

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

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

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

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

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

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

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

Lambdas have no annotations and no docstring

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

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

Now, foo has documentation:

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

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

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

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

<lambda> lambda (...)

But we can hack them on:

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

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

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

Lambdas can only return an expression

Lambdas can’t return complex statements, only expressions.

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

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

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

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

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

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

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

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

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

import timeit

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

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

And now:

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

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

Conclusion

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

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

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

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


回答 6

我同意nosklo的建议:如果需要给函数命名,请使用deflambda当我只是将简短的代码片段传递给另一个函数时,我会保留函数,例如:

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

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

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

回答 7

在同意其他答案的同时,有时它更具可读性。这是一个lambda方便使用的示例,在用例中,我经常遇到N维defaultdict
这是一个例子:

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

我发现它比def为第二维创建更具可读性。对于更大的尺寸,这一点更为重要。

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

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

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


回答 8

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

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

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

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

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

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


回答 9

Lambda的一个重要限制是它们除了表达式外不能包含其他任何内容。一个lambda表达式几乎不可能产生除琐碎的副作用之外的其他任何东西,因为它的身体不能像人体一样富裕。def “ ed函数”。

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

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

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

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

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

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

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


回答 10

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

考虑一个简单的例子,

# 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
  • Computation time.
  • Function without name.
  • To achieve One function and many use functionality.

Considering a simple example,

# 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

回答 11

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

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

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

or

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

回答 12

我发现的lambda的一种用途是在调试消息中。

由于可以懒惰地评估lambda,因此您可以使用以下代码:

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

而不是可能很昂贵:

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

即使调试调用由于当前的日志记录级别而没有产生输出,该命令也将处理格式字符串。

当然,要使它按所描述的那样工作,正在使用的日志记录模块必须支持lambda作为“惰性参数”(就像我的日志记录模块一样)。

相同的想法可以应用于按需内容值创建的任何其他惰性评估情况。

例如,此自定义三元运算符:

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)

如果使用lambda,则只会评估由条件选择的表达式,而不会评估lambda。

当然,您可以简单地使用函数而不是lambda,但是对于短表达式而言,lambda更精简。

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

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

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

instead of possibly expensive:

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

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

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

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

For example this custom ternary operator:

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

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

instead of:

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

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

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

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


回答 13

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

EG:

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

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

使用lambda:

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

pythonic方式:

import operator
myFunction(data, operator.add)

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

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

E.G :

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

You want to pass a function that add 2 elements.

Using lambda :

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

The pythonic way :

import operator
myFunction(data, operator.add)

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


回答 14

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

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

因此,我建议继续使用lambda进行此类琐碎的操作,这些操作也并不能真正受益于功能命名所提供的自动文档。

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

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

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


回答 15

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

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

lambda is useful for generating new functions:

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

为什么在lambda中无法打印?

问题:为什么在lambda中无法打印?

为什么不起作用?

lambda: print "x"

这不是一个单一的陈述,还是其他?该文档对于lambda允许的内容似乎有点稀疏…

Why doesn’t this work?

lambda: print "x"

Is this not a single statement, or is it something else? The documentation seems a little sparse on what is allowed in a lambda…


回答 0

一个lambda人的身体必须是一个单一的表情。在Python 2.x中,print是一条语句。但是,在Python 3中,print函数(而函数应用程序是表达式,因此它将在lambda中工作)。如果您使用的是最新的Python 2.x,则可以(并且应该,为了向前兼容:)使用向后打印功能:

In [1324]: from __future__ import print_function

In [1325]: f = lambda x: print(x)

In [1326]: f("HI")
HI

A lambda‘s body has to be a single expression. In Python 2.x, print is a statement. However, in Python 3, print is a function (and a function application is an expression, so it will work in a lambda). You can (and should, for forward compatibility :) use the back-ported print function if you are using the latest Python 2.x:

In [1324]: from __future__ import print_function

In [1325]: f = lambda x: print(x)

In [1326]: f("HI")
HI

回答 1

在我将其用于简单存根的​​情况下,请使用以下方法:

fn = lambda x: sys.stdout.write(str(x) + "\n")

完美地运作。

In cases where I am using this for simple stubbing out I use this:

fn = lambda x: sys.stdout.write(str(x) + "\n")

which works perfectly.


回答 2

你写的等同于

def anon():
    return print "x"

这也会导致SyntaxError,python不允许您分配要在2.xx中打印的值;在python3中,你可以说

lambda: print('hi')

这样做是可行的,因为他们将print更改为函数而不是语句。

what you’ve written is equivalent to

def anon():
    return print "x"

which also results in a SyntaxError, python doesn’t let you assign a value to print in 2.xx; in python3 you could say

lambda: print('hi')

and it would work because they’ve changed print to be a function instead of a statement.


回答 3

Lambda的主体必须是一个返回值的表达式。 print作为语句,不会返回任何东西,甚至也不返回None。同样,您不能将的结果分配给print变量:

>>> x = print "hello"
  File "<stdin>", line 1
    x = print "hello"
            ^
SyntaxError: invalid syntax

您也不能将变量赋值放在lambda中,因为赋值是语句:

>>> lambda y: (x = y)
  File "<stdin>", line 1
    lambda y: (x = y)
                 ^
SyntaxError: invalid syntax

The body of a lambda has to be an expression that returns a value. print, being a statement, doesn’t return anything, not even None. Similarly, you can’t assign the result of print to a variable:

>>> x = print "hello"
  File "<stdin>", line 1
    x = print "hello"
            ^
SyntaxError: invalid syntax

You also can’t put a variable assignment in a lambda, since assignments are statements:

>>> lambda y: (x = y)
  File "<stdin>", line 1
    lambda y: (x = y)
                 ^
SyntaxError: invalid syntax

回答 4

你可以做这样的事情。

创建一个函数以将打印语句转换为函数:

def printf(text):
   print text

并打印:

lambda: printf("Testing")

You can do something like this.

Create a function to transform print statement into a function:

def printf(text):
   print text

And print it:

lambda: printf("Testing")

回答 5

使用Python 3.x,打印可以在lambda中工作,而无需更改lambda的语义。

以特殊的方式使用,这对于调试非常方便。我发布此“最新答案”,因为这是我经常使用的实用技巧。

假设您的“非工具化” lambda为:

lambda: 4

然后,您的“工具化” lambda为:

lambda: (print (3), 4) [1]

With Python 3.x, print CAN work in a lambda, without changing the semantics of the lambda.

Used in a special way this is very handy for debugging. I post this ‘late answer’, because it’s a practical trick that I often use.

Suppose your ‘uninstrumented’ lambda is:

lambda: 4

Then your ‘instrumented’ lambda is:

lambda: (print (3), 4) [1]

回答 6

Lambda的主体必须是单个表达式print是一个声明,很遗憾,它已经退出了。

The body of a lambda has to be a single expression. print is a statement, so it’s out, unfortunately.


回答 7

在这里,您会看到问题的答案。 print它说不是在Python中表达。

Here, you see an answer for your question. print is not expression in Python, it says.


sorted(key = lambda:…)后面的语法

问题:sorted(key = lambda:…)后面的语法

我不太明白该sorted()参数背后的语法:

key=lambda variable: variable[0]

是不是lambda随心所欲?为什么variable在一个什么样的表述中两次dict

I don’t quite understand the syntax behind the sorted() argument:

key=lambda variable: variable[0]

Isn’t lambda arbitrary? Why is variable stated twice in what looks like a dict?


回答 0

key是一个函数,在比较集合的项目之前将调用该函数。传递给的参数key必须是可调用的。

使用lambda创建一个匿名函数(可调用)。在sorted可调用的情况下仅采用一个参数。Python lambda很简单。它只能做并真正返回一件事。

语法lambda是单词,lambda后跟参数名称列表,然后是单个代码块。参数列表和代码块用冒号表示。这类似于在python其他构建体,以及诸如whileforif等。它们都是通常具有代码块的语句。Lambda只是带有代码块的语句的另一个实例。

我们可以将lambda与def的使用进行比较,以创建一个函数。

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

lambda只是为我们提供了一种无需分配名称的方法。这非常适合用作函数的参数。

variable 在此使用两次,因为在冒号的左手边它是参数的名称,而在右手边它在代码块中用于计算某些内容。

key is a function that will be called to transform the collection’s items before they are compared. The parameter passed to key must be something that is callable.

The use of lambda creates an anonymous function (which is callable). In the case of sorted the callable only takes one parameters. Python’s lambda is pretty simple. It can only do and return one thing really.

The syntax of lambda is the word lambda followed by the list of parameter names then a single block of code. The parameter list and code block are delineated by colon. This is similar to other constructs in python as well such as while, for, if and so on. They are all statements that typically have a code block. Lambda is just another instance of a statement with a code block.

We can compare the use of lambda with that of def to create a function.

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

lambda just gives us a way of doing this without assigning a name. Which makes it great for using as a parameter to a function.

variable is used twice here because on the left hand of the colon it is the name of a parameter and on the right hand side it is being used in the code block to compute something.


回答 1

我认为这里的所有答案都很好地涵盖了lambda函数在sorted()上下文中的作用的核心,但是我仍然感觉缺乏对直观理解的描述,所以这里是我的两分钱。

为了完整起见,我先说一下显而易见的事情:sorted()返回已排序元素的列表,以及是否要以特定方式排序或是否要对元素的复杂列表进行排序(例如,嵌套列表或元组列表),我们可以调用key参数。

对我来说,关键参数的直观理解,为什么它必须是可调用的以及使用lambda作为(匿名)可调用函数来完成此操作的过程分为两个部分。

  1. 最终,使用lamba意味着您不必编写(定义)整个函数,就像一个例子所提供的那样。Lambda函数可以被创建,使用和立即销毁-因此它们不会使您的代码与只会被使用一次的更多代码捆绑在一起。据我了解,这是lambda函数的核心实用程序,它在此类角色中的应用广泛。它的语法纯属约定,从本质上讲,这通常是程序语法的本质。学习语法并完成它。

Lambda语法如下:

lambda input_variable(s)好吃的一班轮

例如

In [1]: f00 = lambda x: x/2

In [2]: f00(10)
Out[2]: 5.0

In [3]: (lambda x: x/2)(10)
Out[3]: 5.0

In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0

In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
  1. key参数背后的想法是,它应该接受一组指令,这些指令本质上将把“ sorted()”功能指向那些应该用于排序的列表元素。当它说时key=,它的真正含义是:当我一次遍历列表中的一个元素时(即对于列表中的e),我将把当前元素传递给我在key参数中提供的函数,并使用该元素。创建一个转换后的列表,该列表将通知我最终排序列表的顺序。

看看这个:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)

基本示例:

sorted(mylist)

[2、3、3、4、6、8、23]#所有数字按从小到大的顺序排列。

范例1:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)

[3,3,23,6,2,4,8]#此排序结果对您来说是否直观?

请注意,我的lambda函数告诉sorted在排序之前检查(e)是偶数还是奇数。

可是等等!您可能(或者也许应该)想知道两件事-首先,为什么我的赔率比我的赔率还要高(因为我的关键值似乎是在告诉我的排序函数通过使用中的mod运算符来优先考虑偶数x%2==0)。第二,为什么我的偶数不正常?2先于6吧?通过分析此结果,我们将更深入地了解sorted()’key’参数如何工作,尤其是与匿名lambda函数结合使用时。

首先,您会注意到虽然赔率先于偶数,但偶数本身并未排序。为什么是这样??让我们阅读文档

关键函数从Python 2.4开始,list.sort()和sorted()都添加了一个关键参数,以指定要在进行比较之前在每个列表元素上调用的函数。

我们必须在这里在各行之间进行一些阅读,但这告诉我们,sort函数仅被调用一次,并且如果我们指定key参数,那么我们将按key函数指向我们的值进行排序。

那么使用模数返回的示例又是什么呢?布尔值:True == 1False == 0。那么排序如何处理这个键?它基本上将原始列表转换为1和0的序列。

[3,6,3,2,4,8,23]变为[0,1,0,1,1,1,0]

现在我们到了某个地方。对转换后的列表进行排序会得到什么?

[0,0,0,1,1,1,1]

好的,现在我们知道了为什么赔率要高于平均赔率了。但是,下一个问题是:为什么最终列表中的6仍然排在2之前?嗯,这很容易-因为排序只发生一次!即那些1仍然代表原始列表值,它们处于彼此相对的原始位置。由于排序仅发生一次,并且我们不调用任何排序函数来将原始偶数值从低到高排序,因此这些值相对于彼此保持原始顺序。

那么最后的问题是:当我打印出最终的排序列表时,我如何在概念上思考布尔值的顺序如何转换回原始值?

Sorted()是一种内置方法(事实)使用称为Timsort的混合排序算法结合了合并排序和插入排序的各个方面。在我看来,当您调用它时,有一种机制可以将这些值保存在内存中,并将它们与由(…!)lambda函数确定的布尔标识(掩码)捆绑在一起。顺序由通过lambda函数计算出的布尔身份确定,但请记住,这些子列表(一个和一个零)本身并不按其原始值排序。因此,最终列表虽然由奇数和偶数组织,但不会按子列表排序(在这种情况下,偶数是乱序的)。赔率排序的事实是因为它们在原始列表中已经是巧合的。从所有这些中得出的结论是,当lambda进行该转换时,将保留子列表的原始顺序。

那么,这一切与原始问题有何关系,更重要的是,我们对如何使用关键参数和lambda实现sorted()的直觉?

该lambda函数可以被视为指向我们需要排序的值的指针,它是将值映射到由lambda函数转换后的布尔值的指针,还是其在嵌套列表tuple中的特定元素, dict等,同样由lambda函数确定。

让我们尝试预测当我运行以下代码时会发生什么。

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])

我的sorted电话显然说:“请对该列表进行排序”。关键参数通过对mylist中的每个元素(x)说,返回该元素的索引1,然后按lambda函数。由于我们有一个元组列表,因此我们可以从该元组返回一个索引元素。这样我们得到:

[(6,2,8),(3,5,8),(6,8,5),(2,9,4)]

运行该代码,您会发现这就是命令。尝试索引整数列表,您会发现代码中断。

这是一个冗长的解释,但是我希望这有助于“整理”您对使用lambda函数作为sorted()及以后的关键参数的直觉。

I think all of the answers here cover the core of what the lambda function does in the context of sorted() quite nicely, however I still feel like a description that leads to an intuitive understanding is lacking, so here is my two cents.

For the sake of completeness, I’ll state the obvious up front: sorted() returns a list of sorted elements and if we want to sort in a particular way or if we want to sort a complex list of elements (e.g. nested lists or a list of tuples) we can invoke the key argument.

For me, the intuitive understanding of the key argument, why it has to be callable, and the use of lambda as the (anonymous) callable function to accomplish this comes in two parts.

  1. Using lamba ultimately means you don’t have to write (define) an entire function, like the one sblom provided an example of. Lambda functions are created, used, and immediately destroyed – so they don’t funk up your code with more code that will only ever be used once. This, as I understand it, is the core utility of the lambda function and its applications for such roles are broad. Its syntax is purely by convention, which is in essence the nature of programmatic syntax in general. Learn the syntax and be done with it.

Lambda syntax is as follows:

lambda input_variable(s): tasty one liner

e.g.

In [1]: f00 = lambda x: x/2

In [2]: f00(10)
Out[2]: 5.0

In [3]: (lambda x: x/2)(10)
Out[3]: 5.0

In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0

In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
  1. The idea behind the key argument is that it should take in a set of instructions that will essentially point the ‘sorted()’ function at those list elements which should used to sort by. When it says key=, what it really means is: As I iterate through the list one element at a time (i.e. for e in list), I’m going to pass the current element to the function I provide in the key argument and use that to create a transformed list which will inform me on the order of final sorted list.

Check it out:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)

Base example:

sorted(mylist)

[2, 3, 3, 4, 6, 8, 23] # all numbers are in order from small to large.

Example 1:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)

[3, 3, 23, 6, 2, 4, 8] # Does this sorted result make intuitive sense to you?

Notice that my lambda function told sorted to check if (e) was even or odd before sorting.

BUT WAIT! You may (or perhaps should) be wondering two things – first, why are my odds coming before my evens (since my key value seems to be telling my sorted function to prioritize evens by using the mod operator in x%2==0). Second, why are my evens out of order? 2 comes before 6 right? By analyzing this result, we’ll learn something deeper about how the sorted() ‘key’ argument works, especially in conjunction with the anonymous lambda function.

Firstly, you’ll notice that while the odds come before the evens, the evens themselves are not sorted. Why is this?? Lets read the docs:

Key Functions Starting with Python 2.4, both list.sort() and sorted() added a key parameter to specify a function to be called on each list element prior to making comparisons.

We have to do a little bit of reading between the lines here, but what this tells us is that the sort function is only called once, and if we specify the key argument, then we sort by the value that key function points us to.

So what does the example using a modulo return? A boolean value: True == 1, False == 0. So how does sorted deal with this key? It basically transforms the original list to a sequence of 1s and 0s.

[3,6,3,2,4,8,23] becomes [0,1,0,1,1,1,0]

Now we’re getting somewhere. What do you get when you sort the transformed list?

[0,0,0,1,1,1,1]

Okay, so now we know why the odds come before the evens. But the next question is: Why does the 6 still come before the 2 in my final list? Well that’s easy – its because sorting only happens once! i.e. Those 1s still represent the original list values, which are in their original positions relative to each other. Since sorting only happens once, and we don’t call any kind of sort function to order the original even values from low to high, those values remain in their original order relative to one another.

The final question is then this: How do I think conceptually about how the order of my boolean values get transformed back in to the original values when I print out the final sorted list?

Sorted() is a built-in method that (fun fact) uses a hybrid sorting algorithm called Timsort that combines aspects of merge sort and insertion sort. It seems clear to me that when you call it, there is a mechanic that holds these values in memory and bundles them with their boolean identity (mask) determined by (…!) the lambda function. The order is determined by their boolean identity calculated from the lambda function, but keep in mind that these sublists (of one’s and zeros) are not themselves sorted by their original values. Hence, the final list, while organized by Odds and Evens, is not sorted by sublist (the evens in this case are out of order). The fact that the odds are ordered is because they were already in order by coincidence in the original list. The takeaway from all this is that when lambda does that transformation, the original order of the sublists are retained.

So how does this all relate back to the original question, and more importantly, our intuition on how we should implement sorted() with its key argument and lambda?

That lambda function can be thought of as a pointer that points to the values we need to sort by, whether its a pointer mapping a value to its boolean transformed by the lambda function, or if its a particular element in a nested list, tuple, dict, etc., again determined by the lambda function.

Lets try and predict what happens when I run the following code.

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])

My sorted call obviously says, “Please sort this list”. The key argument makes that a little more specific by saying, for each element (x) in mylist, return index 1 of that element, then sort all of the elements of the original list ‘mylist’ by the sorted order of the list calculated by the lambda function. Since we have a list of tuples, we can return an indexed element from that tuple. So we get:

[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]

Run that code, and you’ll find that this is the order. Try indexing a list of integers and you’ll find that the code breaks.

This was a long winded explanation, but I hope this helps to ‘sort’ your intuition on the use of lambda functions as the key argument in sorted() and beyond.


回答 2

lambda是一个Python关键字,用于生成匿名函数

>>> (lambda x: x+2)(3)
5

lambda is a Python keyword that is used to generate anonymous functions.

>>> (lambda x: x+2)(3)
5

回答 3

variable左侧:是参数名称。采用variable右侧正在使用的参数。

意思几乎完全相同:

def some_method(variable):
  return variable[0]

The variable left of the : is a parameter name. The use of variable on the right is making use of the parameter.

Means almost exactly the same as:

def some_method(variable):
  return variable[0]

回答 4

使用key = lambda的sorted()函数的另一个示例。让我们考虑一下您有一个元组列表。在每个元组中,您都有汽车的品牌,型号和重量,并且您想要按品牌,型号或重量对这个元组列表进行排序。您可以使用lambda来完成。

cars = [('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000), ('bmw', 'x5', 1700)]

print(sorted(cars, key=lambda car: car[0]))
print(sorted(cars, key=lambda car: car[1]))
print(sorted(cars, key=lambda car: car[2]))

结果:

[('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000)]
[('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100)]
[('citroen', 'xsara', 1100), ('bmw', 'x5', 1700), ('lincoln', 'navigator', 2000)]

One more example of usage sorted() function with key=lambda. Let’s consider you have a list of tuples. In each tuple you have a brand, model and weight of the car and you want to sort this list of tuples by brand, model or weight. You can do it with lambda.

cars = [('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000), ('bmw', 'x5', 1700)]

print(sorted(cars, key=lambda car: car[0]))
print(sorted(cars, key=lambda car: car[1]))
print(sorted(cars, key=lambda car: car[2]))

Results:

[('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100), ('lincoln', 'navigator', 2000)]
[('lincoln', 'navigator', 2000), ('bmw', 'x5', '1700'), ('citroen', 'xsara', 1100)]
[('citroen', 'xsara', 1100), ('bmw', 'x5', 1700), ('lincoln', 'navigator', 2000)]

回答 5

lambda是匿名函数,不是任意函数。接受的参数将是您正在使用的变量以及对其进行排序的列。

lambda is an anonymous function, not an arbitrary function. The parameter being accepted would be the variable you’re working with, and the column in which you’re sorting it on.


回答 6

由于在的上下文中询问了lambda的用法,因此也请sorted()看看https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

Since the usage of lambda was asked in the context of sorted(), take a look at this as well https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions


回答 7

换个说法,排序函数中的键(可选。要执行以决定顺序的函数。默认为None)需要一个函数,而您使用的是lambda。

要定义lambda,请指定要排序的对象属性,而python的内置排序函数将自动处理它。

如果要按多个属性排序,则分配key = lambda x:(property1,property2)。

要指定排序方式,请将sorted函数的第三个参数(可选。布尔值。False将按升序排序,True将按降序排序。默认值为False)传递reverse = true。

Just to rephrase, the key (Optional. A Function to execute to decide the order. Default is None) in sorted functions expects a function and you use lambda.

To define lambda, you specify the object property you want to sort and python’s built-in sorted function will automatically take care of it.

If you want to sort by multiple properties then assign key = lambda x: (property1, property2).

To specify order-by, pass reverse= true as the third argument(Optional. A Boolean. False will sort ascending, True will sort descending. Default is False) of sorted function.


回答 8

简单且不耗时的答案,并提供与所提问题相关的示例,请 按照以下示例操作:

 user = [{"name": "Dough", "age": 55}, 
            {"name": "Ben", "age": 44}, 
            {"name": "Citrus", "age": 33},
            {"name": "Abdullah", "age":22},
            ]
    print(sorted(user, key=lambda el: el["name"]))
    print(sorted(user, key= lambda y: y["age"]))

查看列表中的名称,它们以D,B,C和A开头。如果您注意到年龄,则分别是55、44、33和22。第一个打印代码

print(sorted(user, key=lambda el: el["name"]))

结果为:

[{'name': 'Abdullah', 'age': 22}, 
{'name': 'Ben', 'age': 44}, 
{'name': 'Citrus', 'age': 33}, 
{'name': 'Dough', 'age': 55}]

对名称进行排序,因为通过key = lambda el:el [“ name”]我们对名称进行排序,并且名称按字母顺序返回。

第二次印刷代码

print(sorted(user, key= lambda y: y["age"]))

结果:

[{'name': 'Abdullah', 'age': 22},
 {'name': 'Citrus', 'age': 33},
 {'name': 'Ben', 'age': 44}, 
 {'name': 'Dough', 'age': 55}]

按年龄排序,因此列表按年龄升序返回。

尝试使用此代码可以更好地理解。

Simple and not time consuming answer with an example relevant to the question asked Follow this example:

 user = [{"name": "Dough", "age": 55}, 
            {"name": "Ben", "age": 44}, 
            {"name": "Citrus", "age": 33},
            {"name": "Abdullah", "age":22},
            ]
    print(sorted(user, key=lambda el: el["name"]))
    print(sorted(user, key= lambda y: y["age"]))

Look at the names in the list, they starts with D, B, C and A. And if you notice the ages, they are 55, 44, 33 and 22. The first print code

print(sorted(user, key=lambda el: el["name"]))

Results to:

[{'name': 'Abdullah', 'age': 22}, 
{'name': 'Ben', 'age': 44}, 
{'name': 'Citrus', 'age': 33}, 
{'name': 'Dough', 'age': 55}]

sorts the name, because by key=lambda el: el[“name”] we are sorting the names and the names return in alphabetical order.

The second print code

print(sorted(user, key= lambda y: y["age"]))

Result:

[{'name': 'Abdullah', 'age': 22},
 {'name': 'Citrus', 'age': 33},
 {'name': 'Ben', 'age': 44}, 
 {'name': 'Dough', 'age': 55}]

sorts by age, and hence the list returns by ascending order of age.

Try this code for better understanding.


E731不分配lambda表达式,使用def

问题:E731不分配lambda表达式,使用def

每当我使用lambda表达式时,都会收到此pep8警告。不建议使用lambda表达式吗?如果不是,为什么?

I get this pep8 warning whenever I use lambda expressions. Are lambda expressions not recommended? If not why?


回答 0

您遇到的PEP-8中的建议是:

始终使用def语句代替将lambda表达式直接绑定到名称的赋值语句。

是:

def f(x): return 2*x 

没有:

f = lambda x: 2*x 

第一种形式表示结果函数对象的名称专门为’f’而不是通用的'<lambda>’。通常,这对于回溯和字符串表示形式更为有用。使用赋值语句消除了lambda表达式可以提供的优于显式def语句的唯一好处(即,它可以嵌入到较大的表达式中)

为名称分配lambda基本上只是复制了def– 的功能-通常,最好以一种单一的方式进行操作以避免混淆并提高清晰度。

lambda的合法用例是您要在不分配功能的情况下使用该功能,例如:

sorted(players, key=lambda player: player.rank)

通常,反对这样做的主要理由是def语句将导致更多的代码行。我对此的主要回应是:是的,这很好。除非您是打高尔夫球的人,否则不应该减少行数:一目了然。

The recommendation in PEP-8 you are running into is:

Always use a def statement instead of an assignment statement that binds a lambda expression directly to a name.

Yes:

def f(x): return 2*x 

No:

f = lambda x: 2*x 

The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘<lambda>’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)

Assigning lambdas to names basically just duplicates the functionality of def – and in general, it’s best to do something a single way to avoid confusion and increase clarity.

The legitimate use case for lambda is where you want to use a function without assigning it, e.g:

sorted(players, key=lambda player: player.rank)

In general, the main argument against doing this is that def statements will result in more lines of code. My main response to that would be: yes, and that is fine. Unless you are code golfing, minimising the number of lines isn’t something you should be doing: go for clear over short.


回答 1

这是一个故事,我有一个简单的lambda函数,我使用了两次。

a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)

这只是为了表示,我已经遇到了几个不同的版本。

现在,为了保持干燥状态,我开始重用此通用lambda。

f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

在这一点上,我的代码质量检查器抱怨lambda是一个命名函数,因此我将其转换为一个函数。

def f(x):
    return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

现在,检查者抱怨函数必须在前后插入一个空白行。

def f(x):
    return x + offset

a = map(f, simple_list)
b = map(f, another_simple_list)

在这里,我们现在有6行代码,而不是原始的2行,但没有增加可读性,也没有增加pythonic的代码。在这一点上,代码检查器抱怨该函数没有文档字符串。

在我看来,最好在合理的情况下避免并破坏该规则,请运用您的判断。

Here is the story, I had a simple lambda function which I was using twice.

a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)

This is just for the representation, I have faced couple of different versions of this.

Now, to keep things DRY, I start to reuse this common lambda.

f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

At this point my code quality checker complains about lambda being a named function so I convert it into a function.

def f(x):
    return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

Now the checker complains that a function has to be bounded by one blank line before and after.

def f(x):
    return x + offset

a = map(f, simple_list)
b = map(f, another_simple_list)

Here we have now 6 lines of code instead of original 2 lines with no increase in readability and no increase in being pythonic. At this point the code checker complains about the function not having docstrings.

In my opinion this rule better be avoided and broken when it makes sense, use your judgement.


回答 2

Lattyware是完全正确的:基本上,PEP-8希望您避免诸如此类的事情

f = lambda x: 2 * x

而是使用

def f(x):
    return 2 * x

但是,正如最近 bug报告(2014年8月),语句,如下面现在是否符合:

a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x

由于我的PEP-8检查器尚未正确实现此功能,因此我暂时关闭了E731。

Lattyware is absolutely right: Basically PEP-8 wants you to avoid things like

f = lambda x: 2 * x

and instead use

def f(x):
    return 2 * x

However, as addressed in a recent bugreport (Aug 2014), statements such as the following are now compliant:

a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x

Since my PEP-8 checker doesn’t implement this correctly yet, I turned off E731 for the time being.


回答 3

我还遇到了甚至无法使用def(ined)函数的情况。

class SomeClass(object):
  # pep-8 does not allow this
  f = lambda x: x + 1  # NOQA

  def not_reachable(self, x):
    return x + 1

  @staticmethod
  def also_not_reachable(x):
    return x + 1

  @classmethod
  def also_not_reachable(cls, x):
    return x + 1

  some_mapping = {
      'object1': {'name': "Object 1", 'func': f},
      'object2': {'name': "Object 2", 'func': some_other_func},
  }

在这种情况下,我真的很想做一个属于该类的映射。映射中的某些对象需要相同的功能。将命名函数放在类之外是不合逻辑的。我还没有找到从类主体内部引用方法(静态方法,类方法或普通方法)的方法。运行代码时,尚不存在SomeClass。因此,也不可能从类中引用它。

I also encountered a situation in which it was even impossible to use a def(ined) function.

class SomeClass(object):
  # pep-8 does not allow this
  f = lambda x: x + 1  # NOQA

  def not_reachable(self, x):
    return x + 1

  @staticmethod
  def also_not_reachable(x):
    return x + 1

  @classmethod
  def also_not_reachable(cls, x):
    return x + 1

  some_mapping = {
      'object1': {'name': "Object 1", 'func': f},
      'object2': {'name': "Object 2", 'func': some_other_func},
  }

In this case, I really wanted to make a mapping which belonged to the class. Some objects in the mapping needed the same function. It would be illogical to put the a named function outside of the class. I have not found a way to refer to a method (staticmethod, classmethod or normal) from inside the class body. SomeClass does not exist yet when the code is run. So referring to it from the class isn’t possible either.


如何在Python中使用Lambda进行排序

问题:如何在Python中使用Lambda进行排序

在Python中,我试图按日期与lambda排序。我无法理解我的错误消息。消息是:

<lambda>() takes exactly 1 argument (2 given)

我的电话是

a = sorted(a, lambda x: x.modified, reverse=True)

In Python, I am trying to sort by date with lambda. I can’t understand my error message. The message is:

<lambda>() takes exactly 1 argument (2 given)

The line I have is

a = sorted(a, lambda x: x.modified, reverse=True)

回答 0

使用

a = sorted(a, key=lambda x: x.modified, reverse=True)
#             ^^^^

在Python 2.x上,该sorted函数按以下顺序使用其参数:

sorted(iterable, cmp=None, key=None, reverse=False)

因此,如果没有key=,您传入的函数将被视为带有cmp2个参数的函数。

Use

a = sorted(a, key=lambda x: x.modified, reverse=True)
#             ^^^^

On Python 2.x, the sorted function takes its arguments in this order:

sorted(iterable, cmp=None, key=None, reverse=False)

so without the key=, the function you pass in will be considered a cmp function which takes 2 arguments.


回答 1

lst = [('candy','30','100'), ('apple','10','200'), ('baby','20','300')]
lst.sort(key=lambda x:x[1])
print(lst)

它将打印如下:

[('apple', '10', '200'), ('baby', '20', '300'), ('candy', '30', '100')]
lst = [('candy','30','100'), ('apple','10','200'), ('baby','20','300')]
lst.sort(key=lambda x:x[1])
print(lst)

It will print as following:

[('apple', '10', '200'), ('baby', '20', '300'), ('candy', '30', '100')]

回答 2

Python列表具有两种内置的数据排序方式:

sort() — A method that modifies the list in-place
sorted() — A built-in function that builds a new sorted list from an iterable

根据您的要求,您可以选择以下两种:

如果要保留原始列表,可以使用排序功能;如果不需要原始列表,则可以使用排序功能。

在进行排序之前,我们需要了解lambda。

lambda是一个匿名函数,一个匿名函数是一个没有名称定义的函数,这篇文章似乎很好地解释了它。

https://www.programiz.com/python-programming/anonymous-function

Lambda函数非常适合内联调用,因为它们只有一个表达式被评估并返回。它们的lambda语法为:

lambda参数:表达式

让我们看看如何使用排序功能:

student_tuples = [('john', 'A', 15),('jane', 'B', 12),('dave', 'B', 10),]
sorted(student_tuples, key=lambda student: student[2]) 

输出:[[‘dave’,’B’,10),(’jane’,’B’,12),(’john’,’A’,15)]

在这里,我们可以看到具有元组的列表student_tuples是基于提供为student [2]的关键参数进行排序的。

Python lists have two built-in ways to sort data:

sort() — A method that modifies the list in-place
sorted() — A built-in function that builds a new sorted list from an iterable

Based on your requirement you can choose among these two:

if you want to keep original list ,you can use sorted function or if you don’t need original list you can use sort function.

Before going on sort or sorted ,we need to understand lambda.

A lambda is an anonymous function and an anonymous function is a function that is defined without a name, this post seems to explain it pretty nicely.

https://www.programiz.com/python-programming/anonymous-function

Lambda functions are nice for calling in-line because they only have one expression which is evaluated and returned. They syntax for a lambda is:

lambda arguments: expression

let’s see how to use sorted function:

student_tuples = [('john', 'A', 15),('jane', 'B', 12),('dave', 'B', 10),]
sorted(student_tuples, key=lambda student: student[2]) 

output: [(‘dave’, ‘B’, 10), (‘jane’, ‘B’, 12), (‘john’, ‘A’, 15)]

Here we can see list student_tuples having tuples is sorted based on key parameter provided that is student[2].


回答 3

您正在尝试将关键函数与lambda函数一起使用。

Python和其他语言(例如C#或F#)使用lambda函数

另外,关于关键功能以及根据文档

无论list.sort()排序()具有一个关键参数来指定一个函数被调用之前,进行比较每个列表元件上。

key参数的值应该是一个采用单个参数并返回用于排序目的键的函数。该技术之所以快捷,是因为对于每个输入记录,键函数仅被调用一次。

因此,键函数具有参数键,并且确实可以接收lambda函数。

Real Python中,有一个很好的用法示例。假设您有以下清单

ids = ['id1', 'id100', 'id2', 'id22', 'id3', 'id30']

并希望对其“整数”进行排序。然后,你会做类似的事情

sorted_ids = sorted(ids, key=lambda x: int(x[2:])) # Integer sort

并打印它会给

['id1', 'id2', 'id3', 'id22', 'id30', 'id100']

在您的特定情况下,您只缺少key=在lambda之前写东西。因此,您需要使用以下内容

a = sorted(a, key=lambda x: x.modified, reverse=True)

You’re trying to use key functions with lambda functions.

Python and other languages like C# or F# use lambda functions.

Also, when it comes to key functions and according to the documentation

Both list.sort() and sorted() have a key parameter to specify a function to be called on each list element prior to making comparisons.

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes. This technique is fast because the key function is called exactly once for each input record.

So, key functions have a parameter key and it can indeed receive a lambda function.

In Real Python there’s a nice example of its usage. Let’s say you have the following list

ids = ['id1', 'id100', 'id2', 'id22', 'id3', 'id30']

and want to sort through its “integers”. Then, you’d do something like

sorted_ids = sorted(ids, key=lambda x: int(x[2:])) # Integer sort

and printing it would give

['id1', 'id2', 'id3', 'id22', 'id30', 'id100']

In your particular case, you’re only missing to write key= before lambda. So, you’d want to use the following

a = sorted(a, key=lambda x: x.modified, reverse=True)

使用’key’和lambda表达式的python max函数

问题:使用’key’和lambda表达式的python max函数

我来自OOP背景,尝试学习python。我正在使用max使用lambda表达式返回列表中Player具有最大类型的实例的函数。totalScoreplayers

def winner():
    w = max(players, key=lambda p: p.totalScore)

该函数正确返回Player具有maximum 类型的实例totalScore。我对以下三件事感到困惑:

  1. max功能如何工作?它正在采取什么论点?我查看了文档,但听不懂。
  2. keymax函数中关键字的用途是什么?我知道它也用于sort功能上下文
  3. lambda表达式的含义?如何阅读它们?它们如何运作?

这些都是非常笨拙的概念性问题,但可以帮助我理解语言。如果您可以提供示例进行解释,将有所帮助。谢谢

I come from OOP background and trying to learn python. I am using the max function which uses a lambda expression to return the instance of type Player having maximum totalScore among the list players.

def winner():
    w = max(players, key=lambda p: p.totalScore)

The function correctly returns instance of type Player having maximum totalScore. I am confused about the following three things:

  1. How does the max function work? What are the arguments it is taking? I looked at the documentation but failed to understand.
  2. What is use of the keyword key in max function? I know it is also used in context of sort function
  3. Meaning of the lambda expression? How to read them? How do they work?

These are all very noobish conceptual questions but will help me understand the language. It would help if you could give examples to explain. Thanks


回答 0

lambda 是一个匿名函数,它等效于:

def func(p):
   return p.totalScore     

现在max变成:

max(players, key=func)

但是由于def语句是复合语句,因此不能在需要表达式的地方使用它们,这就是有时lambda使用的原因。

请注意,这lambda等效于您在的return语句中输入的内容def。因此,您不能在内使用语句lambda,仅允许使用表达式。


怎么max办?

max(a,b,c,… [,key = func])->值

使用单个可迭代参数,返回其最大的项目。具有两个或更多参数,返回最大参数。

因此,它仅返回最大的对象。


key工作如何?

在Python 2中,默认情况下会key根据对象类型(例如,字符串始终大于整数)基于一组规则比较项目。

要在比较之前修改对象,或基于特定的属性/索引进行比较,必须使用key参数。

范例1:

一个简单的示例,假设您有一个字符串形式的数字列表,但是您想按其整数值比较这些项目。

>>> lis = ['1', '100', '111', '2']

这里max使用它们的原始值比较项目(按字母顺序比较字符串,这样您就可以得到'2'输出):

>>> max(lis)
'2'

要通过整数比较项目,请使用key简单的lambda

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

示例2:应用于max元组列表。

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

默认情况下,max将按第一个索引比较项目。如果第一个索引相同,则将比较第二个索引。在我的示例中,所有项目都有唯一的第一个索引,因此您将获得以下答案:

>>> max(lis)
(4, 'e')

但是,如果您想通过索引1的值比较每个项目,该怎么办?简单:使用lambda

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

比较包含不同类型对象的可迭代项

混合项目清单:

lis = ['1','100','111','2', 2, 2.57]

在Python 2中,可以比较两种不同类型的项目

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

但是在Python 3中,您不能再这样做了

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

但这可行,因为我们正在比较每个对象的整数版本:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'

lambda is an anonymous function, it is equivalent to:

def func(p):
   return p.totalScore     

Now max becomes:

max(players, key=func)

But as def statements are compound statements they can’t be used where an expression is required, that’s why sometimes lambda‘s are used.

Note that lambda is equivalent to what you’d put in a return statement of a def. Thus, you can’t use statements inside a lambda, only expressions are allowed.


What does max do?

max(a, b, c, …[, key=func]) -> value

With a single iterable argument, return its largest item. With two or more arguments, return the largest argument.

So, it simply returns the object that is the largest.


How does key work?

By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).

To modify the object before comparison, or to compare based on a particular attribute/index, you’ve to use the key argument.

Example 1:

A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.

>>> lis = ['1', '100', '111', '2']

Here max compares the items using their original values (strings are compared lexicographically so you’d get '2' as output) :

>>> max(lis)
'2'

To compare the items by their integer value use key with a simple lambda:

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

Example 2: Applying max to a list of tuples.

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

By default max will compare the items by the first index. If the first index is the same then it’ll compare the second index. As in my example, all items have a unique first index, so you’d get this as the answer:

>>> max(lis)
(4, 'e')

But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

Comparing items in an iterable that contains objects of different type:

List with mixed items:

lis = ['1','100','111','2', 2, 2.57]

In Python 2 it is possible to compare items of two different types:

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

But in Python 3 you can’t do that any more:

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

But this works, as we are comparing integer version of each object:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'

回答 1

的高度简化版本max

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

关于lambda:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

Strongly simplified version of max:

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

Regarding lambda:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

回答 2

max函数如何工作?

它寻找可迭代的“最大”项。我假设您可以查找内容,但如果不是,则可以循环查找,即列表或字符串。

max函数中关键字key的用途是什么?我知道它也用于排序功能的上下文中

Key是一个lambda函数,它将告诉max可迭代对象中的哪些对象大于其他对象。假设您正在排序自己创建的某个对象,而不是像整数这样的显而易见的对象。

lambda表达式的含义?如何阅读它们?它们如何运作?

这是一个更大的问题。简单来说,lambda是一个您可以传递的功能,并且其他代码也可以使用它。以这个为例:

def sum(a, b, f):
    return (f(a) + f(b))

这需要两个对象,ab和一个函数f。它调用f()每个对象,然后将它们添加在一起。所以看这个电话:

>>> sum(2, 2, lambda a:  a * 2)
8

sum()需要2,并在其上调用lambda表达式。因此f(a)变为2 * 2,变为4。然后为进行此操作b,并将两者加在一起。

用不那么简单的术语来说,lambda来自lambda演算,这是一个返回函数的函数。用于表达计算的非常酷的数学概念。你可以阅读有关在这里,然后居然明白在这里

最好多读一遍,因为lambda可能会造成混淆,而且还不清楚它们的用处。在这里检查。

How does the max function work?

It looks for the “largest” item in an iterable. I’ll assume that you can look up what that is, but if not, it’s something you can loop over, i.e. a list or string.

What is use of the keyword key in max function? I know it is also used in context of sort function

Key is a lambda function that will tell max which objects in the iterable are larger than others. Say if you were sorting some object that you created yourself, and not something obvious, like integers.

Meaning of the lambda expression? How to read them? How do they work?

That’s sort of a larger question. In simple terms, a lambda is a function you can pass around, and have other pieces of code use it. Take this for example:

def sum(a, b, f):
    return (f(a) + f(b))

This takes two objects, a and b, and a function f. It calls f() on each object, then adds them together. So look at this call:

>>> sum(2, 2, lambda a:  a * 2)
8

sum() takes 2, and calls the lambda expression on it. So f(a) becomes 2 * 2, which becomes 4. It then does this for b, and adds the two together.

In not so simple terms, lambdas come from lambda calculus, which is the idea of a function that returns a function; a very cool math concept for expressing computation. You can read about that here, and then actually understand it here.

It’s probably better to read about this a little more, as lambdas can be confusing, and it’s not immediately obvious how useful they are. Check here.


回答 3

max函数用于获取最大值iterable

迭代器可以是列表,元组,字典对象等。甚至可以像您提供的示例中那样是自定义对象。

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

因此,key=func基本上,我们可以将一个可选参数传递key给该函数,在该函数的基础上,对给定的迭代器/参数进行排序并返回最大值。

lambda是一个充当伪函数的python关键字。因此,当您将player对象传递给它时,它将返回player.totalScore。因此,传递给函数的iterable max将根据提供给它的对象的key totalScore进行排序,player并返回player具有maximum 的who totalScore

如果未key提供任何参数,则根据默认的Python顺序返回最大值。

例子 –

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')

max function is used to get the maximum out of an iterable.

The iterators may be lists, tuples, dict objects, etc. Or even custom objects as in the example you provided.

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

So, the key=func basically allows us to pass an optional argument key to the function on whose basis is the given iterator/arguments are sorted & the maximum is returned.

lambda is a python keyword that acts as a pseudo function. So, when you pass player object to it, it will return player.totalScore. Thus, the iterable passed over to function max will sort according to the key totalScore of the player objects given to it & will return the player who has maximum totalScore.

If no key argument is provided, the maximum is returned according to default Python orderings.

Examples –

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')

回答 4

根据文档

max(iterable [,key])
max(arg1,arg2,* args [,key])
返回可迭代的最大项目或两个或多个参数中的最大项目。

如果提供了一个位置参数,则iterable必须是非空的Iterable(例如,非空的字符串,元组或列表)。返回iterable中最大的项目。如果提供了两个或多个位置自变量,则返回最大的位置自变量。

可选的key参数指定一个单参数排序函数,例如用于list.sort()的函数。如果提供了key参数,则必须采用关键字形式(例如max(a,b,c,key = func))。

这就是说,在这种情况下,您要提供一个列表players。然后,该max函数将遍历列表中的所有项目,并将它们相互比较以获得“最大值”。

可以想象,使用复杂的对象(例如player确定其比较值)比较棘手,因此将为您提供key参数,以确定max函数如何确定每个对象的值player。在这种情况下,您使用的是lambda函数,说“对于每个pin playersget p.totalscore并将其用作比较的值”。

According to the documentation:

max(iterable[, key])
max(arg1, arg2, *args[, key])
Return the largest item in an iterable or the largest of two or more arguments.

If one positional argument is provided, iterable must be a non-empty iterable (such as a non-empty string, tuple or list). The largest item in the iterable is returned. If two or more positional arguments are provided, the largest of the positional arguments is returned.

The optional key argument specifies a one-argument ordering function like that used for list.sort(). The key argument, if supplied, must be in keyword form (for example, max(a,b,c,key=func)).

What this is saying is that in your case, you are providing a list, in this case players. Then the max function will iterate over all the items in the list and compare them to each other to get a “maximum”.

As you can imagine, with a complex object like a player determining its value for comparison is tricky, so you are given the key argument to determine how the max function will decide the value of each player. In this case, you are using a lambda function to say “for each p in players get p.totalscore and use that as his value for comparison”.


回答 5

max内置函数,该函数接受第一个参数iterable(例如列表或元组)

关键字参数key具有默认值,None但它接受要评估的函数,将其视为基于函数评估可迭代的包装器

考虑以下示例字典:

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

例如:

>>> max(d.keys())
'sword'

如您所见,如果只传递不带kwarg的可迭代对象(将函数传递给key),它将返回key的最大值(按字母顺序)

例如 可能不是需要按字母顺序查找键的最大值,而是可能需要根据键的长度查找最大键:

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

在此示例中,lambda函数返回的键长度将被迭代,因此在评估值而不是按字母顺序考虑时,它将跟踪键的最大长度并返回具有最大长度的键

例如

>>> max(d.keys(), key=lambda x: d[x])
'friend'

在此示例中,lambda函数返回具有最大值的相应字典键的值

max is built in function which takes first argument an iterable (like list or tuple)

keyword argument key has it’s default value None but it accept function to evaluate, consider it as wrapper which evaluates iterable based on function

Consider this example dictionary:

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

Ex:

>>> max(d.keys())
'sword'

As you can see if you only pass the iterable without kwarg(a function to key) it is returning maximum value of key(alphabetically)

Ex. Instead of finding max value of key alphabetically you might need to find max key by length of key:

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

in this example lambda function is returning length of key which will be iterated hence while evaluating values instead of considering alphabetically it will keep track of max length of key and returns key which has max length

Ex.

>>> max(d.keys(), key=lambda x: d[x])
'friend'

in this example lambda function is returning value of corresponding dictionary key which has maximum value


Chalice-面向AWS的Python无服务器微框架

Chalice是一个用python编写无服务器应用程序的框架。它允许您快速创建和部署使用AWS Lambda的应用程序。它提供:

  • 用于创建、部署和管理应用程序的命令行工具
  • 基于修饰器的API,用于与Amazon API Gateway、Amazon S3、Amazon SNS、Amazon SQS和其他AWS服务集成
  • 自动生成IAM策略

您可以创建睡觉接口:

from chalice import Chalice

app = Chalice(app_name="helloworld")

@app.route("/")
def index():
    return {"hello": "world"}

定期运行的任务:

from chalice import Chalice, Rate

app = Chalice(app_name="helloworld")

# Automatically runs every 5 minutes
@app.schedule(Rate(5, unit=Rate.MINUTES))
def periodic_task(event):
    return {"hello": "world"}

您可以将lambda函数连接到S3事件:

from chalice import Chalice

app = Chalice(app_name="helloworld")

# Whenever an object is uploaded to 'mybucket'
# this lambda function will be invoked.

@app.on_s3_event(bucket='mybucket')
def handler(event):
    print("Object uploaded for bucket: %s, key: %s"
          % (event.bucket, event.key))

以及SQS队列:

from chalice import Chalice

app = Chalice(app_name="helloworld")

# Invoke this lambda function whenever a message
# is sent to the ``my-queue-name`` SQS queue.

@app.on_sqs_message(queue='my-queue-name')
def handler(event):
    for record in event:
        print("Message body: %s" % record.body)

以及其他几个AWS资源

一旦您编写了代码,您只需运行chalice deployChalice负责部署您的应用程序

$ chalice deploy
...
https://endpoint/dev

$ curl https://endpoint/api
{"hello": "world"}

在不到30秒的时间内启动并运行。试一试这个项目,并在Github上与我们分享您的反馈

文档是可用的here

快速入门

在本教程中,您将使用chalice用于创建和部署基本睡觉应用编程接口的命令行实用程序。此快速入门使用Python3.7,但AWS Chalice支持AWS Lambda支持的所有版本的Python,包括python2.7、python3.6、python3.7、python3.8。我们建议您使用Python3的版本。您可以在Python download page

要安装Chalice,我们将首先在python3.7中创建并激活一个虚拟环境:

$ python3 --version
Python 3.7.3
$ python3 -m venv venv37
$ . venv37/bin/activate

接下来,我们将使用以下命令安装圣杯pip

$ python3 -m pip install chalice

您可以通过运行以下命令来验证您是否安装了圣杯:

$ chalice --help
Usage: chalice [OPTIONS] COMMAND [ARGS]...
...

凭据

在部署应用程序之前,请确保已配置凭据。如果您之前已将计算机配置为运行boto3(AWS SDK For Python)或AWS CLI,则可以跳过此部分

如果这是您第一次为AWS配置凭据,您可以按照以下步骤快速入门:

$ mkdir ~/.aws
$ cat >> ~/.aws/config
[default]
aws_access_key_id=YOUR_ACCESS_KEY_HERE
aws_secret_access_key=YOUR_SECRET_ACCESS_KEY
region=YOUR_REGION (such as us-west-2, us-west-1, etc)

如果需要有关所有支持的凭据配置方法的详细信息,请参阅boto3 docs

创建您的项目

接下来我们要做的是使用chalice用于创建新项目的命令:

$ chalice new-project helloworld

这将创建一个helloworld目录。cd放入此目录。您将看到已为您创建了几个文件:

$ cd helloworld
$ ls -la
drwxr-xr-x   .chalice
-rw-r--r--   app.py
-rw-r--r--   requirements.txt

您可以忽略.chalice目录,我们现在要关注的两个主要文件是app.pyrequirements.txt

我们来看一下app.py文件:

from chalice import Chalice

app = Chalice(app_name='helloworld')


@app.route('/')
def index():
    return {'hello': 'world'}

这个new-project命令创建了定义单个视图的示例应用程序,/,调用时将返回JSON正文{"hello": "world"}

正在部署

让我们部署此应用程序。一定要确保你在helloworld目录并运行chalice deploy

$ chalice deploy
Creating deployment package.
Creating IAM role: helloworld-dev
Creating lambda function: helloworld-dev
Creating Rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-west-2:12345:function:helloworld-dev
  - Rest API URL: https://abcd.execute-api.us-west-2.amazonaws.com/api/

现在,您已经使用API Gateway和Lambda启动并运行了API:

$ curl https://qxea58oupc.execute-api.us-west-2.amazonaws.com/api/
{"hello": "world"}

尝试从中更改返回的词典index()功能。然后,您可以通过运行以下命令重新部署更改chalice deploy

下一步

现在,您已经使用以下工具创建了您的第一个应用程序chalice您可以修改您的app.py文件并重新运行chalice deploy要重新部署更改,请执行以下操作

此时,您可以采取以下几个步骤

  • Tutorials-从多个指导性教程中进行选择,这些教程将为您提供Chalice各种功能的分步示例
  • Topics-深入研究圣杯特定领域的文档。其中包含比教程更详细的文档
  • API Reference-有关Chalice公共API的所有类和方法的低级参考文档

如果您已经完成了对Chalice的实验,并且您想要进行清理,您可以使用chalice delete命令,则Chalice将删除它在运行chalice deploy命令

$ chalice delete
Deleting Rest API: abcd4kwyl4
Deleting function aws:arn:lambda:region:123456789:helloworld-dev
Deleting IAM Role helloworld-dev

反馈

我们也很想听到你的消息。请为您想要查看的其他功能创建任何Github问题,请访问https://github.com/aws/chalice/issues您也可以在GITER上与我们聊天:https://gitter.im/awslabs/chalice

(lambda)函数闭包捕获了什么?

问题:(lambda)函数闭包捕获了什么?

最近,我开始玩弄Python,并且在闭包的工作方式中遇到了一些奇怪的事情。考虑以下代码:

adders=[0,1,2,3]

for i in [0,1,2,3]:
   adders[i]=lambda a: i+a

print adders[1](3)

它构建了一个简单的函数数组,这些函数接受单个输入并返回该输入加数字后的结果。这些函数在for循环中构造,其中迭代器i0到运行3。对于这些数字中的每一个,lambda都会创建一个函数,将其捕获i并将其添加到函数的输入中。最后一行使用参数作为参数调用第二个lambda函数3。令我惊讶的Yield6

我期望一个4。我的推论是:在Python中,一切都是对象,因此每个变量都是指向它的指针。为创建lambda闭包时i,我希望它存储一个指向当前由指向的整数对象的指针i。这意味着,当i分配一个新的整数对象时,它不应影响先前创建的闭包。可悲的是,adders在调试器中检查该阵列是否可以完成。所有的lambda功能指的最后一个值i3,其结果adders[1](3)返回6

这让我想知道以下几点:

  • 闭包到底捕获了什么?
  • 用最优雅的方法说服lambda功能捕获当前值,i而该方法在i更改其值时不会受到影响?

Recently I started playing around with Python and I came around something peculiar in the way closures work. Consider the following code:

adders=[None, None, None, None]

for i in [0,1,2,3]:
   adders[i]=lambda a: i+a

print adders[1](3)

It builds a simple array of functions that take a single input and return that input added by a number. The functions are constructed in for loop where the iterator i runs from 0 to 3. For each of these numbers a lambda function is created which captures i and adds it to the function’s input. The last line calls the second lambda function with 3 as a parameter. To my surprise the output was 6.

I expected a 4. My reasoning was: in Python everything is an object and thus every variable is essential a pointer to it. When creating the lambda closures for i, I expected it to store a pointer to the integer object currently pointed to by i. That means that when i assigned a new integer object it shouldn’t effect the previously created closures. Sadly, inspecting the adders array within a debugger shows that it does. All lambda functions refer to the last value of i, 3, which results in adders[1](3) returning 6.

Which make me wonder about the following:

  • What do the closures capture exactly?
  • What is the most elegant way to convince the lambda functions to capture the current value of i in a way that will not be affected when i changes its value?

回答 0

您的第二个问题已经回答,但第一个问题是:

闭包究竟捕获了什么?

Python的作用域是动态且词汇丰富的。闭包将始终记住变量的名称和范围,而不是其指向的对象。由于示例中的所有函数都是在同一作用域中创建的,并且使用相同的变量名,因此它们始终引用相同的变量。

编辑:关于您如何解决此问题的其他问题,有两种方法可以想到:

  1. 最简洁但并非严格等效的方法是Adrien Plisson推荐的方法。创建带有额外参数的lambda,并将额外参数的默认值设置为要保留的对象。

  2. 每次创建lambda时,创建一个新的作用域会更加冗长一些,但hacky会更少:

    >>> adders = [0,1,2,3]
    >>> for i in [0,1,2,3]:
    ...     adders[i] = (lambda b: lambda a: b + a)(i)
    ...     
    >>> adders[1](3)
    4
    >>> adders[2](3)
    5

    这里的范围是使用新函数(为简便起见,为lambda)创建的,该函数绑定了其参数,并将要绑定的值作为参数传递。但是,在实际代码中,您很可能会使用普通函数而不是lambda来创建新范围:

    def createAdder(x):
        return lambda y: y + x
    adders = [createAdder(i) for i in range(4)]

Your second question has been answered, but as for your first:

what does the closure capture exactly?

Scoping in Python is dynamic and lexical. A closure will always remember the name and scope of the variable, not the object it’s pointing to. Since all the functions in your example are created in the same scope and use the same variable name, they always refer to the same variable.

EDIT: Regarding your other question of how to overcome this, there are two ways that come to mind:

  1. The most concise, but not strictly equivalent way is the one recommended by Adrien Plisson. Create a lambda with an extra argument, and set the extra argument’s default value to the object you want preserved.

  2. A little more verbose but less hacky would be to create a new scope each time you create the lambda:

    >>> adders = [0,1,2,3]
    >>> for i in [0,1,2,3]:
    ...     adders[i] = (lambda b: lambda a: b + a)(i)
    ...     
    >>> adders[1](3)
    4
    >>> adders[2](3)
    5
    

    The scope here is created using a new function (a lambda, for brevity), which binds its argument, and passing the value you want to bind as the argument. In real code, though, you most likely will have an ordinary function instead of the lambda to create the new scope:

    def createAdder(x):
        return lambda y: y + x
    adders = [createAdder(i) for i in range(4)]
    

回答 1

您可以使用具有默认值的参数来强制捕获变量:

>>> for i in [0,1,2,3]:
...    adders[i]=lambda a,i=i: i+a  # note the dummy parameter with a default value
...
>>> print( adders[1](3) )
4

想法是声明一个参数(命名为i),并为其提供要捕获的变量的默认值(的值 i

you may force the capture of a variable using an argument with a default value:

>>> for i in [0,1,2,3]:
...    adders[i]=lambda a,i=i: i+a  # note the dummy parameter with a default value
...
>>> print( adders[1](3) )
4

the idea is to declare a parameter (cleverly named i) and give it a default value of the variable you want to capture (the value of i)


回答 2

为了完整起见,第二个问题的另一个答案是:您可以在functools模块中使用partial

通过像Chris Lutz所建议的那样从运算符导入add,示例变为:

from functools import partial
from operator import add   # add(a, b) -- Same as a + b.

adders = [0,1,2,3]
for i in [0,1,2,3]:
   # store callable object with first argument given as (current) i
   adders[i] = partial(add, i) 

print adders[1](3)

For completeness another answer to your second question: You could use partial in the functools module.

With importing add from operator as Chris Lutz proposed the example becomes:

from functools import partial
from operator import add   # add(a, b) -- Same as a + b.

adders = [0,1,2,3]
for i in [0,1,2,3]:
   # store callable object with first argument given as (current) i
   adders[i] = partial(add, i) 

print adders[1](3)

回答 3

考虑以下代码:

x = "foo"

def print_x():
    print x

x = "bar"

print_x() # Outputs "bar"

我认为大多数人都不会觉得这令人困惑。这是预期的行为。

那么,为什么人们认为循环完成会有所不同呢?我知道我自己犯了这个错误,但我不知道为什么。是循环吗?也许是lambda?

毕竟,循环只是以下内容的简化版本:

adders= [0,1,2,3]
i = 0
adders[i] = lambda a: i+a
i = 1
adders[i] = lambda a: i+a
i = 2
adders[i] = lambda a: i+a
i = 3
adders[i] = lambda a: i+a

Consider the following code:

x = "foo"

def print_x():
    print x

x = "bar"

print_x() # Outputs "bar"

I think most people won’t find this confusing at all. It is the expected behaviour.

So, why do people think it would be different when it is done in a loop? I know I did that mistake myself, but I don’t know why. It is the loop? Or perhaps the lambda?

After all, the loop is just a shorter version of:

adders= [0,1,2,3]
i = 0
adders[i] = lambda a: i+a
i = 1
adders[i] = lambda a: i+a
i = 2
adders[i] = lambda a: i+a
i = 3
adders[i] = lambda a: i+a

回答 4

为了回答第二个问题,最优雅的方法是使用一个接受两个参数而不是数组的函数:

add = lambda a, b: a + b
add(1, 3)

但是,在这里使用lambda有点愚蠢。Python为我们operator提供了该模块,该模块为基本运算符提供了功能接口。上面的lambda仅在调用加法运算符时就有不必要的开销:

from operator import add
add(1, 3)

我了解到您正在玩耍,尝试探索该语言,但是我无法想象出现这样的情况:我会使用一系列函数来阻止Python的范围异常。

如果需要,可以编写一个使用数组索引语法的小类:

class Adders(object):
    def __getitem__(self, item):
        return lambda a: a + item

adders = Adders()
adders[1](3)

In answer to your second question, the most elegant way to do this would be to use a function that takes two parameters instead of an array:

add = lambda a, b: a + b
add(1, 3)

However, using lambda here is a bit silly. Python gives us the operator module, which provides a functional interface to the basic operators. The lambda above has unnecessary overhead just to call the addition operator:

from operator import add
add(1, 3)

I understand that you’re playing around, trying to explore the language, but I can’t imagine a situation I would use an array of functions where Python’s scoping weirdness would get in the way.

If you wanted, you could write a small class that uses your array-indexing syntax:

class Adders(object):
    def __getitem__(self, item):
        return lambda a: a + item

adders = Adders()
adders[1](3)

回答 5

这是一个新的示例,突出显示了闭包的数据结构和内容,以帮助阐明何时“保存”了封闭的上下文。

def make_funcs():
    i = 42
    my_str = "hi"

    f_one = lambda: i

    i += 1
    f_two = lambda: i+1

    f_three = lambda: my_str
    return f_one, f_two, f_three

f_1, f_2, f_3 = make_funcs()

什么是封闭?

>>> print f_1.func_closure, f_1.func_closure[0].cell_contents
(<cell at 0x106a99a28: int object at 0x7fbb20c11170>,) 43 

值得注意的是,my_str不在f1的闭包中。

f2的闭包是什么?

>>> print f_2.func_closure, f_2.func_closure[0].cell_contents
(<cell at 0x106a99a28: int object at 0x7fbb20c11170>,) 43

从内存地址中注意到,两个闭包都包含相同的对象。所以,你可以开始将lambda函数视为对范围的引用。但是,my_str不在f_1或f_2的闭包中,i不在f_3的闭包中(未显示),这表明闭包对象本身是不同的对象。

闭包对象本身是否是同一对象?

>>> print f_1.func_closure is f_2.func_closure
False

Here’s a new example that highlights the data structure and contents of a closure, to help clarify when the enclosing context is “saved.”

def make_funcs():
    i = 42
    my_str = "hi"

    f_one = lambda: i

    i += 1
    f_two = lambda: i+1

    f_three = lambda: my_str
    return f_one, f_two, f_three

f_1, f_2, f_3 = make_funcs()

What is in a closure?

>>> print f_1.func_closure, f_1.func_closure[0].cell_contents
(<cell at 0x106a99a28: int object at 0x7fbb20c11170>,) 43 

Notably, my_str is not in f1’s closure.

What’s in f2’s closure?

>>> print f_2.func_closure, f_2.func_closure[0].cell_contents
(<cell at 0x106a99a28: int object at 0x7fbb20c11170>,) 43

Notice (from the memory addresses) that both closures contain the same objects. So, you can start to think of the lambda function as having a reference to the scope. However, my_str is not in the closure for f_1 or f_2, and i is not in the closure for f_3 (not shown), which suggests the closure objects themselves are distinct objects.

Are the closure objects themselves the same object?

>>> print f_1.func_closure is f_2.func_closure
False

有没有办法在python的lambda中执行“如果”

问题:有没有办法在python的lambda中执行“如果”

python 2.6中,我想这样做:

f = lambda x: if x==2 print x else raise Exception()
f(2) #should print "2"
f(3) #should throw an exception

这显然不是语法。是否可以执行ifin lambda,如果可以,该怎么做?

谢谢

In python 2.6, I want to do:

f = lambda x: if x==2 print x else raise Exception()
f(2) #should print "2"
f(3) #should throw an exception

This clearly isn’t the syntax. Is it possible to perform an if in lambda and if so how to do it?

thanks


回答 0

您要寻找的语法:

lambda x: True if x % 2 == 0 else False

但是您不能使用printraise使用lambda。

The syntax you’re looking for:

lambda x: True if x % 2 == 0 else False

But you can’t use print or raise in a lambda.


回答 1

为什么不只是定义一个函数?

def f(x):
    if x == 2:
        print(x)
    else:
        raise ValueError

在这种情况下,确实没有理由使用lambda。

why don’t you just define a function?

def f(x):
    if x == 2:
        print(x)
    else:
        raise ValueError

there really is no justification to use lambda in this case.


回答 2

到目前为止,我可能写的最糟糕的python行:

f = lambda x: sys.stdout.write(["2\n",][2*(x==2)-2])

如果您打印x == 2,

如果x!= 2,则加注。

Probably the worst python line I’ve written so far:

f = lambda x: sys.stdout.write(["2\n",][2*(x==2)-2])

If x == 2 you print,

if x != 2 you raise.


回答 3

如果您确实要这样做,则可以在lambda中轻松引发异常。

def Raise(exception):
    raise exception
x = lambda y: 1 if y < 2 else Raise(ValueError("invalid value"))

这是一个好主意吗?我的本能通常是将错误报告放在lambda之外。使其值为None并在调用方中引发错误。不过,我不认为这从本质上讲是邪恶的-我认为“ y if x else z”语法本身更糟-只需确保您没有试图将过多内容放入lambda主体即可。

You can easily raise an exception in a lambda, if that’s what you really want to do.

def Raise(exception):
    raise exception
x = lambda y: 1 if y < 2 else Raise(ValueError("invalid value"))

Is this a good idea? My instinct in general is to leave the error reporting out of lambdas; let it have a value of None and raise the error in the caller. I don’t think this is inherently evil, though–I consider the “y if x else z” syntax itself worse–just make sure you’re not trying to stuff too much into a lambda body.


回答 4

就允许使用的内容而言,Python中的Lambda相当严格。特别是,你不能有任何关键字(除了运营商喜欢andnotor,等)在他们的身上。

因此,您无法在示例中使用lambda(因为您无法使用raise),但是如果您愿意就此作答,则可以使用:

f = lambda x: x == 2 and x or None

Lambdas in Python are fairly restrictive with regard to what you’re allowed to use. Specifically, you can’t have any keywords (except for operators like and, not, or, etc) in their body.

So, there’s no way you could use a lambda for your example (because you can’t use raise), but if you’re willing to concede on that… You could use:

f = lambda x: x == 2 and x or None

回答 5

请注意,您可以在lambda定义中使用其他else … if语句:

f = lambda x: 1 if x>0 else 0 if x ==0 else -1

note you can use several else…if statements in your lambda definition:

f = lambda x: 1 if x>0 else 0 if x ==0 else -1

回答 6

如果仍要打印,则可以导入以后的模块

from __future__ import print_function

f = lambda x: print(x) if x%2 == 0 else False

If you still want to print you can import future module

from __future__ import print_function

f = lambda x: print(x) if x%2 == 0 else False

回答 7

您还可以使用逻辑运算符来进行类似条件运算的操作

func = lambda element: (expression and DoSomething) or DoSomethingIfExpressionIsFalse

您可以在此处查看有关逻辑运算符的更多信息

You can also use Logical Operators to have something like a Conditional

func = lambda element: (expression and DoSomething) or DoSomethingIfExpressionIsFalse

You can see more about Logical Operators here


回答 8

您真正需要的是

def fun():
    raise Exception()
f = lambda x:print x if x==2 else fun()

现在以您需要的方式调用该函数

f(2)
f(3)

what you need exactly is

def fun():
    raise Exception()
f = lambda x:print x if x==2 else fun()

now call the function the way you need

f(2)
f(3)

回答 9

此代码段应帮助您:

x = lambda age: 'Older' if age > 30 else 'Younger'

print(x(40))

This snippet should help you:

x = lambda age: 'Older' if age > 30 else 'Younger'

print(x(40))

回答 10

以下示例代码对我有用。不知道它是否与这个问题直接相关,但希望在其他情况下有帮助。

a = ''.join(map(lambda x: str(x*2) if x%2==0 else "", range(10)))

Following sample code works for me. Not sure if it directly relates to this question, but hope it helps in some other cases.

a = ''.join(map(lambda x: str(x*2) if x%2==0 else "", range(10)))

回答 11

尝试一下:

is_even = lambda x: True if x % 2 == 0 else False
print(is_even(10))
print(is_even(11))

出:

True
False

Try it:

is_even = lambda x: True if x % 2 == 0 else False
print(is_even(10))
print(is_even(11))

Out:

True
False

回答 12

在lambda中执行if的一种简单方法是使用列表理解。

您不能在lambda中引发异常,但这是Python 3.x中一种类似于您的示例的方式:

f = lambda x: print(x) if x==2 else print("exception")

另一个例子:

如果M则返回1,否则返回0

f = lambda x: 1 if x=="M" else 0

An easy way to perform an if in lambda is by using list comprehension.

You can’t raise an exception in lambda, but this is a way in Python 3.x to do something close to your example:

f = lambda x: print(x) if x==2 else print("exception")

Another example:

return 1 if M otherwise 0

f = lambda x: 1 if x=="M" else 0