Can you assign variables in a lambda?

删除回忆录丶 提交于 2020-08-04 04:30:27

问题


I was using a lambda statement to perform math, and happened to repeatedly use one certain value. Therefore I was wondering if it was possible to assign and use a variable within a lambda statement.

I have tried things like:

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

However this just raises errors, and I was wondering if there was a way to do this.


回答1:


Nope, you can't. Only expressions allowed in lambda:

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

You could, however, define a second lambda inside the lambda and immediately call it with the parameter you want. (Whether that's really better might be another question.)

>>> 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)

Of course, both the outer and the inner lambda can have more than one parameter, i.e. you can define multiple "variables" at once. The benefit of this approach over, e.g., defining a second lambda outside of the first is, that you can still also use the original parameters (not possible if you invoked a with b pre-calculated) and you have to do the calculation for b only once (other than repeatedly invoking a function for the calculation of b within a).


Also, inspired by the top answer to the linked question, you could also define one or more variables as part of a list comprehension or generator within the lambda, and then get the next (first and only) result from that generator or list:

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

However, I think the intent behind the lambda-in-a-lambda is a bit clearer. Finally, keep in mind that instead of a one-line lambda, you could also just use a much clearer three-line def statement...


Also, starting with Python 3.8, there will be assignment expressions, which should make it possible to write something like this. (Note that I could not try/verify this as I do not have Python 3.8 yet.)

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



回答2:


You can assign variables in lambda functions is you use exec:

>>> a = lambda: exec('global x; x = 1')
>>>a()
>>>x
1



回答3:


You can create 2 different lambda functions and pass one to the other. For example,

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



回答4:


You can just pass your lambda an argument which passes it along to another argument if you wish:

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



回答5:


I've cooked up this recipe for python 3.8+ using PEP572 Assignment Expressions to assign arbitrary variables and execute arbitrary expressions.

# 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

So the pattern is:

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
    )
)

This may be simplified if you know the truthiness of any particular expression.

That being said, if you want to assign a variable to reuse inside a lambda, you probably should consider writing a normal function.




回答6:


You can instead use a bit of creativity, for example if you want to do some evaluation to an equation and assign the result to a variable it can be done like this:

class Results:
    res = 0

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



回答7:


Im no expert at this, but the way i did it was by modifying globals() or locals() like this:

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

or if it's inside a function:

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

you could also use update() instead of __setitem__() if you wanted to, but that's a bit redundant.



来源:https://stackoverflow.com/questions/45337189/can-you-assign-variables-in-a-lambda

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!