【问题标题】:Can you assign variables in a lambda?您可以在 lambda 中分配变量吗?
【发布时间】:2017-07-26 20:51:39
【问题描述】:

我正在使用lambda 语句来执行数学运算,并且碰巧重复使用了某个特定值。因此,我想知道是否可以在 lambda 语句中分配和使用变量。

我尝试过类似的方法:

a = lambda n:(b=3+2*n) #[my math here]

但这只会引发错误,我想知道是否有办法做到这一点。

【问题讨论】:

  • 我不认为这真的是那个问题的重复。虽然标题非常相似,但实际问题似乎有点不同。 (其实就是想投票重开,忘了防骗锤了……)
  • 您可以使用海象运算符(在 Python 3.8 中)在 lambda 中分配变量。

标签: python variables lambda


【解决方案1】:

不,你不能。 lambda 中只允许使用表达式:

lambda_expr        ::=  "lambda" [parameter_list]: expression
lambda_expr_nocond ::=  "lambda" [parameter_list]: expression_nocond

但是,您可以在lambda 中定义 second lambda inside 并立即使用所需的参数调用它。 (这是否真的更好可能是另一个问题。)

>>> a = lambda n: ((3+2*n), n*(3+2*n))  # for reference, with repetition
>>> a(42)
(87, 3654)
>>> a2 = lambda n: (lambda b: (b, n*b))(3+2*n)  # lambda inside lambda
>>> a2(42)
(87, 3654)
>>> a3 = lambda n: (lambda b=3+2*n: (b, n*b))()  # using default parameter
>>> a3(42)
(87, 3654)

当然,外部和内部 lambda 可以有多个参数,即您可以一次定义多个“变量”。这种方法的好处是,例如,在第一个 lambda outside 中定义第二个 lambda,您仍然可以使用原始参数(如果您使用 b pre-调用 a 则不可能)计算)并且您只需对b 进行一次计算(除了在a 内重复调用计算b 的函数)。


此外,受top answer to the linked question 的启发,您还可以在 lambda 中定义一个或多个变量作为列表理解或生成器的一部分,然后从该生成器或列表中获取 next(第一个也是唯一一个)结果:

>>> a4 = lambda n: next((b, n*b) for b in [3+2*n])
>>> a4(42)
(87, 3654)

但是,我认为 lambda-in-a-lambda 背后的意图更加清晰。最后,请记住,除了单行 lambda,您还可以使用更清晰的三行 def 语句...


另外,从 Python 3.8 开始,将会有 assignment expressions应该可以编写这样的东西。 (请注意,由于我还没有 Python 3.8,因此我无法尝试/验证这一点。)

>>> a5 = lambda n: ((b := 3+2*n), n*b))

【讨论】:

  • 致较新的访问者:请注意,最后一个命题不适用于 Python 3.8,因为 lambda 函数中不允许使用赋值表达式。
【解决方案2】:

如果你愿意,你可以只传递你的 lambda 一个参数,然后将它传递给另一个参数:

>>> b = lambda x: 3 + 2*x
>>> a = lambda y: y * b(y)
>>> a(1)
5
>>> a(2)
14

【讨论】:

  • 不,我试图做的是使用传递给 lambda 的参数进行计算,但我反复对参数执行3+2*n 操作,所以我想将它分配给一个变量。
【解决方案3】:

您可以创建 2 个不同的 lambda 函数并将一个传递给另一个。例如,

b = lambda x: 3+2*x
a = lambda y: [my math here using variable b(y)]

【讨论】:

    【解决方案4】:

    我已经使用 PEP572 赋值表达式为 python 3.8+ 编写了这个配方来分配任意变量并执行任意表达式。

    # python 3.8b1
    lambda a: (
        (bool(b:=a**2) or 1)
        and (bool(c:=a-b) or 1)
        and not print(f'compute: {a} + {b} + {c}')
        and (
            (ret:=a + b + c) or ret)
        )
    )
    tst(0) 
    # prints: "compute: 0 + 0 + 0"; returns: 0
    tst(1)
    # prints: "compute: 1 + 1 + 0"; returns: 2
    tst(8)
    # prints: "compute: 8 + 64 + -56"; returns: 16
    

    所以模式是:

    lambda: [*vars]: (
        (bool(a:=[expr(*vars)]) or 1)
        and (bool([expr]) or 1)
        and bool([always true expr])
        and not bool([always false expr])
        and (
            # parentheses required so `result:=` doesn't capture the `or result` part
            (result:=[result expr]) or result
        )
    )
    

    如果您知道任何特定表达的真实性,这可能会被简化。

    话虽如此,如果你想分配一个变量以在 lambda 中重用,你可能应该考虑编写一个普通函数。

    【讨论】:

      【解决方案5】:

      我不是这方面的专家,但我的做法是修改 globals()locals() 像这样:

      lambda: globals().__setitem__('some_variable', 'some value')
      

      或者如果它在函数内部:

      lambda: locals().__setitem__('some_variable', 'some value')
      

      如果您愿意,也可以使用update() 代替__setitem__(),但这有点多余。

      【讨论】:

        【解决方案6】:

        您可以使用一些创意,例如,如果您想对方程进行一些评估并将结果分配给变量,可以这样做:

        class Results:
            res = 0
        
        clas= Results()
        setattr(clas, 'res', 3+2*4)
        print(clas.res)
        

        【讨论】:

          【解决方案7】:

          你可以用 oop 的方式重写它,就像这样,也许你无论如何都在使用 oop 结构,所以你可以将它集成到那里。

          class example:
               def __init__(self):
                   self.a = None
          
           object = example()
           a = lambda n:(setattr(object, "a", 3+2*n)) #[my math here]
           a(2)
           print(object.a)
          

          输出:

          7

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-03-31
            • 1970-01-01
            • 1970-01-01
            • 2013-06-10
            • 2012-01-30
            • 2012-11-01
            • 2017-09-19
            • 1970-01-01
            相关资源
            最近更新 更多