我有一个对象列表,我想使用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
)

最佳答案

The assignment expression operator := added in 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使您可以在nonlocal s内使用def关键字解决此问题,但是nonlocal不能在lambda s中使用。

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

在某些情况下,您可以使用它来完成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()])()



请不要

...回到原始示例:尽管您无法在外部范围内对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

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)

关于python - Python中Lambda表达式内的赋值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6282042/

10-12 12:20
查看更多