The assignment expression operator := added in Python 3.8 supports assignment inside of lambda expressions. This operator can only appear within a parenthesized (...), bracketed [...], or braced {...} expression for syntactic reasons. For example, we will be able to write the following:

import sys
say_hello = lambda: (
    message := "Hello world",
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

In Python 2, it was possible to perform local assignments as a side effect of list comprehensions.

import sys
say_hello = lambda: (
    [None for message in ["Hello world"]],
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

However, it's not possible to use either of these in your example because your variable flag is in an outer scope, not the lambda's scope. This doesn't have to do with lambda, it's the general behaviour in Python 2. Python 3 lets you get around this with the nonlocal keyword inside of defs, but nonlocal can't be used inside lambdas.

There's a workaround (see below), but while we're on the topic...


In some cases you can use this to do everything inside of a lambda:

(lambda: [
    ['def'
        for sys in [__import__('sys')]
        for math in [__import__('math')]

        for sub in [lambda *vals: None]
        for fun in [lambda *vals: vals[-1]]

        for echo in [lambda *vals: sub(
            sys.stdout.write(u" ".join(map(unicode, vals)) + u"\n"))]

        for Cylinder in [type('Cylinder', (object,), dict(
            __init__ = lambda self, radius, height: sub(
                setattr(self, 'radius', radius),
                setattr(self, 'height', height)),

            volume = property(lambda self: fun(
                ['def' for top_area in [math.pi * self.radius ** 2]],

                self.height * top_area))))]

        for main in [lambda: sub(
            ['loop' for factor in [1, 2, 3] if sub(
                ['def'
                    for my_radius, my_height in [[10 * factor, 20 * factor]]
                    for my_cylinder in [Cylinder(my_radius, my_height)]],

                echo(u"A cylinder with a radius of %.1fcm and a height "
                     u"of %.1fcm has a volume of %.1fcm³."
                     % (my_radius, my_height, my_cylinder.volume)))])]],

    main()])()

A cylinder with a radius of 10.0cm and a height of 20.0cm has a volume of 6283.2cm³.
A cylinder with a radius of 20.0cm and a height of 40.0cm has a volume of 50265.5cm³.
A cylinder with a radius of 30.0cm and a height of 60.0cm has a volume of 169646.0cm³.

Please don't.


...back to your original example: though you can't perform assignments to the flag variable in the outer scope, you can use functions to modify the previously-assigned value.

For example, flag could be an object whose .value we set using setattr:

flag = Object(value=True)
input = [Object(name=''), Object(name='fake_name'), Object(name='')] 
output = filter(lambda o: [
    flag.value or bool(o.name),
    setattr(flag, 'value', flag.value and bool(o.name))
][0], input)
[Object(name=''), Object(name='fake_name')]

If we wanted to fit the above theme, we could use a list comprehension instead of setattr:

    [None for flag.value in [bool(o.name)]]

But really, in serious code you should always use a regular function definition instead of a lambda if you're going to be doing outer assignment.

flag = Object(value=True)
def not_empty_except_first(o):
    result = flag.value or bool(o.name)
    flag.value = flag.value and bool(o.name)
    return result
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(not_empty_except_first, input)
Answer from Jeremy on Stack Overflow
Top answer
1 of 13
287

The assignment expression operator := added in Python 3.8 supports assignment inside of lambda expressions. This operator can only appear within a parenthesized (...), bracketed [...], or braced {...} expression for syntactic reasons. For example, we will be able to write the following:

import sys
say_hello = lambda: (
    message := "Hello world",
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

In Python 2, it was possible to perform local assignments as a side effect of list comprehensions.

import sys
say_hello = lambda: (
    [None for message in ["Hello world"]],
    sys.stdout.write(message + "\n")
)[-1]
say_hello()

However, it's not possible to use either of these in your example because your variable flag is in an outer scope, not the lambda's scope. This doesn't have to do with lambda, it's the general behaviour in Python 2. Python 3 lets you get around this with the nonlocal keyword inside of defs, but nonlocal can't be used inside lambdas.

There's a workaround (see below), but while we're on the topic...


In some cases you can use this to do everything inside of a lambda:

(lambda: [
    ['def'
        for sys in [__import__('sys')]
        for math in [__import__('math')]

        for sub in [lambda *vals: None]
        for fun in [lambda *vals: vals[-1]]

        for echo in [lambda *vals: sub(
            sys.stdout.write(u" ".join(map(unicode, vals)) + u"\n"))]

        for Cylinder in [type('Cylinder', (object,), dict(
            __init__ = lambda self, radius, height: sub(
                setattr(self, 'radius', radius),
                setattr(self, 'height', height)),

            volume = property(lambda self: fun(
                ['def' for top_area in [math.pi * self.radius ** 2]],

                self.height * top_area))))]

        for main in [lambda: sub(
            ['loop' for factor in [1, 2, 3] if sub(
                ['def'
                    for my_radius, my_height in [[10 * factor, 20 * factor]]
                    for my_cylinder in [Cylinder(my_radius, my_height)]],

                echo(u"A cylinder with a radius of %.1fcm and a height "
                     u"of %.1fcm has a volume of %.1fcm³."
                     % (my_radius, my_height, my_cylinder.volume)))])]],

    main()])()

A cylinder with a radius of 10.0cm and a height of 20.0cm has a volume of 6283.2cm³.
A cylinder with a radius of 20.0cm and a height of 40.0cm has a volume of 50265.5cm³.
A cylinder with a radius of 30.0cm and a height of 60.0cm has a volume of 169646.0cm³.

Please don't.


...back to your original example: though you can't perform assignments to the flag variable in the outer scope, you can use functions to modify the previously-assigned value.

For example, flag could be an object whose .value we set using setattr:

flag = Object(value=True)
input = [Object(name=''), Object(name='fake_name'), Object(name='')] 
output = filter(lambda o: [
    flag.value or bool(o.name),
    setattr(flag, 'value', flag.value and bool(o.name))
][0], input)
[Object(name=''), Object(name='fake_name')]

If we wanted to fit the above theme, we could use a list comprehension instead of setattr:

    [None for flag.value in [bool(o.name)]]

But really, in serious code you should always use a regular function definition instead of a lambda if you're going to be doing outer assignment.

flag = Object(value=True)
def not_empty_except_first(o):
    result = flag.value or bool(o.name)
    flag.value = flag.value and bool(o.name)
    return result
input = [Object(name=""), Object(name="fake_name"), Object(name="")] 
output = filter(not_empty_except_first, input)
2 of 13
41

You cannot really maintain state in a filter/lambda expression (unless abusing the global namespace). You can however achieve something similar using the accumulated result being passed around in a reduce() expression:

>>> f = lambda a, b: (a.append(b) or a) if (b not in a) else a
>>> input = ["foo", u"", "bar", "", "", "x"]
>>> reduce(f, input, [])
['foo', u'', 'bar', 'x']
>>> 

You can, of course, tweak the condition a bit. In this case it filters out duplicates, but you can also use a.count(""), for example, to only restrict empty strings.

Needless to say, you can do this but you really shouldn't. :)

Lastly, you can do anything in pure Python lambda: http://vanderwijk.info/blog/pure-lambda-calculus-python/

Discussions

code golf - Python workarounds for assignment in lambda - Code Golf Stack Exchange
This is a tips question for golfing in Python. In Python golfing, it's common for a submission to be a function defined as a lambda. For example, f=lambda x:0**x or x*f(x-1) computes the factoria... More on codegolf.stackexchange.com
🌐 codegolf.stackexchange.com
January 11, 2017
python - Can you assign variables in a lambda? - Stack Overflow
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... More on stackoverflow.com
🌐 stackoverflow.com
Why are assignments not allowed in Python's `lambda` expressions? - Stack Overflow
This is not a duplicate of Assignment inside lambda expression in Python, i.e., I'm not asking how to trick Python into assigning in a lambda expression. I have some λ-calculus background. Consid... More on stackoverflow.com
🌐 stackoverflow.com
python - How to perform an assignment inside a lambda function - Stack Overflow
A lambda can only contain one expression, and statements are not included. You can assign to the map though, by using the operator.setitem() function instead: More on stackoverflow.com
🌐 stackoverflow.com
March 11, 2013
🌐
Quantifiedcode
docs.quantifiedcode.com › python-anti-patterns › correctness › assigning_a_lambda_to_a_variable.html
Assigning a lambda expression to a variable — Python Anti-Patterns documentation
The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)
🌐
Ikriv
ikriv.com › blog
Python: assignment in lambdas – Ivan Krivyakov
TL;DR Use default parameters to simulate assignment in lambdas. Unlike C and C++, in Python assignment is an expression, not a statement.
🌐
YouTube
youtube.com › how to fix your computer
PYTHON : Assignment inside lambda expression in Python - YouTube
PYTHON : Assignment inside lambda expression in Python [ Gift : Animated Search Engine : https://www.hows.tech/p/recommended.html ] PYTHON : Assignment insi...
Published: December 7, 2021
Views: 44
Top answer
1 of 8
30

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. (Tested with Python 3.8.10.)

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

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.

Find elsewhere
Top answer
1 of 7
25

The entire reason lambda exists is that it's an expression.1 If you want something that's like lambda but is a statement, that's just def.

Python expressions cannot contain statements. This is, in fact, fundamental to the language, and Python gets a lot of mileage out of that decision. It's the reason indentation for flow control works instead of being clunky as in many other attempts (like CoffeeScript). It's the reason you can read off the state changes by skimming the first object in each line. It's even part of the reason the language is easy to parse, both for the compiler and for human readers.2

Changing Python to have some way to "escape" the statement-expression divide, except maybe in a very careful and limited way, would turn it into a completely different language, and one that no longer had many of the benefits that cause people to choose Python in the first place.

Changing Python to make most statements expressions (like, say, Ruby) would again turn it into a completely different language without Python's current benefits.

And if Python did make either of those changes, then there'd no longer be a reason for lambda in the first place;2,3 you could just use def statements inside an expression.


What about changing Python to instead make assignments expressions? Well, it should be obvious that would break "you can read off the state changes by skimming the first object in each line". Although Guido usually focuses on the fact that if spam=eggs is an error more often than a useful thing.

The fact that Python does give you ways to get around that when needed, like setattr or even explicitly calling __setitem__ on globals(), doesn't mean it's something that should have direct syntactic support. Something that's very rarely needed doesn't deserve syntactic sugar—and even more so for something that's unusual enough that it should raise eyebrows and/or red flags when it actually is done.


1. I have no idea whether that was Guido's understanding when he originally added lambda back in Python 1.0. But it's definitely the reason lambda wasn't removed in Python 3.0.

2. In fact, Guido has, multiple times, suggested that allowing an LL(1) parser that humans can run in their heads is sufficient reason for the language being statement-based, to the point that other benefits don't even need to be discussed. I wrote about this a few years ago if anyone's interested.

3. If you're wondering why so many languages do have a lambda expression despite already having def: In many languages, ranging from C++ to Ruby, function aren't first-class objects that can be passed around, so they had to invent a second thing that is first-class but works like a function. In others, from Smalltalk to Java, functions don't even exist, only methods, so again, they had to invent a second thing that's not a method but works like one. Python has neither of those problems.

4. A few languages, like C# and JavaScript, actually had perfectly working inline function definitions, but added some kind of lambda syntax as pure syntactic sugar, to make it more concise and less boilerplatey. That might actually be worth doing in Python (although every attempt at a good syntax so far has fallen flat), but it wouldn't be the current lambda syntax, which is nearly as verbose as def.

2 of 7
8

There is a syntax problem: an assignment is a statement, and the body of a lambda can only have expressions. Python's syntax is designed this way1. Check it out at https://docs.python.org/3/reference/grammar.html.

There is also a semantics problem: what does each statement return?

I don't think there is interest in changing this, as lambdas are meant for very simple and short code. Moreover, a statement would allow sequences of statements as well, and that's not desirable for lambdas.

It could be also fixed by selectively allowing certain statements in the lambda body, and specifying the semantics (e.g. an assignment returns None, or returns the assigned value; the latter makes more sense to me). But what's the benefit?

Lambdas and functions are interchangeable. If you really have a use-case for a particular statement in the body of a lambda, you can define a function that executes it, and your specific problem is solved.


Perhaps you can create a syntactic macro to allow that with MacroPy3 (I'm just guessing, as I'm a fan of the project, but still I haven't had the time to dive in it).

For example MacroPy would allow you to define a macro that transforms f[_ * _] into lambda a, b: a * b, so it should not be impossible to define the syntax for a lambda that calls a function you defined.


1 A good reason to not change it is that it would cripple the syntax, because a lambda can be in places where expressions can be. And statements should not. But that's a very subjective remark of my own.

🌐
Execute Program
executeprogram.com › courses › python-for-programmers › lessons › lambda-expressions
Python for Programmers: Lambda Expressions
Because there's only one expression, Python knows that we must want to return it. Because lambdas can only contain expressions, we can't use if, while, for, def, or assignments with =. All of those are statements.
🌐
P-nand-q
p-nand-q.com › python › lambda.html
Stupid lambda tricks - p-nand-q.com
The best solution is to store all local variables in a list, and use list assignment as described above. Here is a quote from section "4.16." from "The Whole Python FAQ:" Not directly. In many cases you can mimic a?b:c with "a and b or c", but there's a flaw: if b is zero (or empty, or None -- anything that tests false) then c will be selected instead.
🌐
Real Python
realpython.com › python-lambda
How to Use Python Lambda Functions – Real Python
June 14, 2025 - The failed test results from the same failure explained in the execution of the unit tests in the previous section. You can add a docstring to a Python lambda via an assignment to __doc__ to document a lambda function.
🌐
Joshdata
joshdata.me › lambda-expressions.html
Lambda Expressions: A Guide
The text variable in the inner function is a different variable than the one in the outer funtion because there is an assignment to text in the inner function. A trick is to make the outer variable a contaier: ... Although Python capture is always by reference, there is a trick for achieving capture by value: assigning default values to lambda expression arguments.
🌐
Python Forum
python-forum.io › thread-903.html
How do I make an assignment inside lambda function?
November 13, 2016 - Good day, having a brain freeze :) How do I set a boolean variable to True inside lambda function? I'm trying to set variable to True on a hotkey(using SystemHotkey lib) : from system_hotkey import SystemHotkey b = False SystemHotkey().register(('c...
🌐
Homedutech
homedutech.com › program-example › assignment-inside-lambda-expression-in-python.html
Assignment inside lambda expression in Python
In Python, lambda expressions are used to create anonymous functions, typically for short and simple operations. However, assignments inside lambda expressions are not supported directly because lambdas are restricted to a single expression. Instead, you should use regular functions (defined ...
🌐
pythontutorials
pythontutorials.net › blog › assignment-inside-lambda-expression-in-python
Can You Assign Variables in Python Lambda Expressions? Filtering to Keep One Empty Object Explained — pythontutorials.net
This means: No loops (for, while), ... statements. No variable assignment statements (e.g., x = 5), as assignments are statements in Python, not expressions....
🌐
Dataquest
dataquest.io › home › blog › how to use a lambda function in python
Lambda Functions in Python (With Examples)
April 21, 2026 - One thing worth calling out: you ... against it. When you assign a lambda to a variable, you're just giving an anonymous function a name, which defeats its purpose....