你能在lambda中分配变量吗?

时间:2017-07-26 20:51:39

标签: python variables lambda

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

我尝试过这样的事情:

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

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

8 个答案:

答案 0 :(得分:4)

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

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

但是,您可以在lambda内定义第二 lambda 并立即使用您想要的参数调用它。 (这真的更好可能是另一个问题。)

>>> 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都可以有多个参数,即你可以定义多个"变量"立刻。这种方法的好处在于,例如,定义第一个在第一个之外,你仍然可以使用原始参数(如果你用{{1}调用a则不可能预计算)并且您必须只对b进行一次计算(除了在b内重复调用b的计算函数之外)。

另外,受top answer to the linked question的启发,您还可以将一个或多个变量定义为lambda中列表推导或生成器的一部分,然后从a(第一个也是唯一一个)获取结果那个生成器或列表:

next

然而,我认为lambda-in-a-lambda背后的意图更清晰一些。最后,请记住,您可以使用更清晰的三行>>> a3 = lambda n: next((b, n*b) for b in [3+2*n]) >>> a3(42) (87, 3654) 语句而不是单行lambda ...

答案 1 :(得分:3)

您可以使用exec:

在lambda函数中指定变量
>>> a = lambda: exec('global x; x = 1')
>>>a()
>>>x
1

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我已经使用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 :(得分:0)

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

var geometry = new THREE.IcosahedronGeometry( 10, 3 );
var material = new THREE.MeshLambertMaterial( {color: 0xff0000} );
sphere = new THREE.Mesh( geometry, material );
sphere.castShadow = true;
sphere.receiveShadow = true;
scene.add(sphere);

答案 6 :(得分:0)

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

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

或是否在函数内部:

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

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

答案 7 :(得分:0)

你可以用 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