繁体   English   中英

您可以在 lambda 中分配变量吗?

[英]Can you assign variables in a lambda?

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

我试过这样的事情:

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

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

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


此外,受链接问题的最佳答案的启发,您还可以将一个或多个变量定义为 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 开始,将会有赋值表达式,这应该可以编写这样的东西。 (使用 Python 3.8.10 测试。)

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

如果您使用 exec,您可以在 lambda 函数中分配变量:

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

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

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

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

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

我已经使用 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 中重用,您可能应该考虑编写一个普通函数。

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

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

或者如果它在函数内部:

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

如果你愿意,你也可以使用update()而不是__setitem__() ,但这有点多余。

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

class Results:
    res = 0

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

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

我希望4年后我迟到的答案会有用

Python 有setattr函数来设置给定对象的属性。 您可以在 lambda 表达式中使用它。

当您想以编程方式正确(抱歉)设置某个类或类的实例时, setattr很有用。 它不经常使用,因为用=表达式直接分配变量更容易。 但是对于 lambdas... 这是一种救赎。

此外,支持 settign 项的迭代(例如列表),您可以使用<iter>.__setitem__

选项 1 如果您知道要分配的变量的名称。

x = lambda nameofvar, value: setattr(__builtins__, nameofvar, value)

# abc does not exist right now. Assigning and setting it to 10
x('abc', 10)
print(abc) # output: 10

alt ,如果要设置对象的属性:

class MyClass:
    my_attr = False
    def __init__(self, value):
        self.value = value
myinstance = MyClass(25)

x = lambda obj, nameofvar, value: setattr(obj, nameofvar, value)
short_x = lambda nameofvar, value: setattr(MyClass, nameofvar, value)
# ^^^ this one works only for MyClass' attributes.

print(MyClass.my_attr) # output: False
x(MyClass, 'my_attr', True) # Changing MyClass' my_attr's value
print(MyClass.my_attr) # output: True
x(MyClass, 'my_attr2', 5) # Assigning new attribute to MyClass
print(MyClass.my_attr2) # output: 5
short_x('my_attr2', 123) # Setting MyClass' my_attr2 to 123
print(MyClass.my_attr2) # output: 123

print(myinstance.value) # output: 25
x(myinstance, 'value', 500)
print(myinstance.value) # output: 500

选项 2 创建一个自定义类并将变量转换为其实例。

class Value:
    def __init__(self, value):
        self.value = value

x = lambda var, newvalue: setattr(var, 'value', newvalue)

a = Value(15)
print(a.value) # output: 15
x(a, 25)
print(a.value) # output: 25

选项 3 设置对象的项目。

lst = [15, 30, 45, 60, 75, 90]

x = lambda iterable, item, value: iterable.__setitem__(item, value)

print(lst) # output: [15, 30, 45, 60, 75, 90]
x(lst, 2, 1000)
print(lst) # output: [15, 30, 1000, 60, 75, 90]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM