Can you assign variables in a lambda?

Viewed 35862

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.

8 Answers

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.

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.

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)

You could rewrite this in a oop way, like this, maybe you are using an oop structure anyways so you could integrate it in there.

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)

Output:

7

i hope that after 4 years my late answer will be useful

Python has setattr function to set attribute of given object. You can use it in your lambda expression.

setattr is useful when you want to programmatically-correctly (sorry) set some class or class' instance. It is not used frequently because it is easier to assign variables directly with = expression. But for lambdas... It is a salvation.

Also, iterables that support settign item (such as list), you can use <iter>.__setitem__.

Option 1. If you know the name of variable you're assigning.

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, if you want to set object's attribute:

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

Option 2. Make a custom class and turn variable into its instance.

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

Option 3. To set object's item.

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]
Related