I've got the following examples:
outer
is a variable defined outside thelambda
. Changes toouter
are seen by thelambda
:
foo = lambda: outer
outer = 'outer'
print(outer) # 'outer'
print(foo()) # 'outer'
outer = 'changed'
print(outer) # 'changed'
print(foo()) # 'changed'
outer
is still a variable defined outside thelambda
. Changes toouter
are still seen by thelambda
, but if the change toouter
is inside thelambda
, then the change toouter
is not seen by the outside scope:
foo = lambda: (outer := 'changed in lambda', print(outer))
outer = 'outer'
print(outer) # 'outer'
print(foo()) # 'changed in lambda'
print(outer) # 'outer'
- The following are examples of when
lambda's
do and don't change an outer scope variable. Each example has adef
function equivalent (with one caveat) which is also shown:
+---------+-----------------------------------------------+--------------------------------------+------------------------+
| Example | `lambda` version | `def` version | change of `outer` |
| | | | seen by outside scope? |
+=========+===============================================+======================================+========================+
| 3a. | ``` | ``` | no |
| | foo = lambda: \ | def foo(): | |
| | (outer := 'changed in lambda', | outer = 'changed in lambda' | |
| | print(outer)) | print(outer) | |
| | outer = 'outer' | outer = 'outer' | |
| | | | |
| | print(outer) # 'outer' | print(outer) # 'outer' | |
| | foo() # 'changed in lambda' | foo() # 'changed in lambda' | |
| | print(outer) # 'outer' | print(outer) # 'outer' | |
| | ``` | ``` | |
+---------+-----------------------------------------------+--------------------------------------+------------------------+
| 3b. | no `lambda` version because | ``` | yes |
| | using `global` in a `lambda` | def foo(): | |
| | seems to be invalid syntax. | global outer | |
| | | outer = 'changed in lambda' | |
| | | print(outer) | |
| | | outer = 'outer' | |
| | | | |
| | | print(outer) # 'outer' | |
| | | foo() # 'changed in lambda' | |
| | | print(outer) # 'changed in lambda' | |
| | | ``` | |
+---------+-----------------------------------------------+--------------------------------------+------------------------+
| 3c. | ``` | ``` | no |
| | foo = lambda: \ | def foo(): | |
| | (outer := ['changed in lambda'], | outer = ['changed in lambda'] | |
| | print(outer)) | print(outer) | |
| | outer = ['outer'] | outer = ['outer'] | |
| | | | |
| | print(outer) # ['outer'] | print(outer) # ['outer'] | |
| | foo() # ['changed in lambda'] | foo() # ['changed in lambda'] | |
| | print(outer) # ['outer'] | print(outer) # ['outer'] | |
| | ``` | ``` | |
+---------+-----------------------------------------------+--------------------------------------+------------------------+
| 3d. | ``` | ``` | yes |
| | foo = lambda: \ | def foo() | |
| | (outer.__setitem__(0, 'changed in lambda'), | outer[0] = 'changed in lambda' | |
| | print(outer)) | print(outer) | |
| | outer = ['outer'] | outer = ['outer'] | |
| | | | |
| | print(outer) # ['outer'] | print(outer) # ['outer'] | |
| | foo() # ['changed in lambda'] | foo() # ['changed in lambda'] | |
| | print(outer) # ['changed in lambda'] | print(outer) # ['changed in lambda'] | |
| | ``` | ``` | |
+---------+-----------------------------------------------+--------------------------------------+------------------------+
Table created using https://www.tablesgenerator.com/text_tables
Where can I learn more about the mechanics of lambda
s and their scope?
Python doc's definition of lambda
goes some ways towards explaining this behavior (emphasis mine):
An anonymous inline function consisting of a single expression which is evaluated when the function is called. The syntax to create a lambda function is
lambda [parameters]: expression