I've got the following examples:
outeris a variable defined outside thelambda. Changes toouterare seen by thelambda:
foo = lambda: outer
outer = 'outer'
print(outer) # 'outer'
print(foo()) # 'outer'
outer = 'changed'
print(outer) # 'changed'
print(foo()) # 'changed'
outeris still a variable defined outside thelambda. Changes toouterare still seen by thelambda, but if the change toouteris inside thelambda, then the change toouteris 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'sdo and don't change an outer scope variable. Each example has adeffunction 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 lambdas 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