Schrödinger's variable
▶ Schrödinger's variable *
The asterisk at the end of the title indicates the example was not present in the first release and has been recently added.
def make_func(): for target in ('a', 2, None): if isinstance(target, str): def f(): print(f'inside f(), {target=}') print(f'just created f(), {target=} at this point!') return f
Output (Python version):
>>> f = make_func() target='a' at this point! >>> f() inside f(), target=None
💡 Explanation:
-
Python doesn't actually bind the value of
targetinf(). It just creates a function that will look uptargetin the surrounding context. -
Since
targetwill continue to be updated until it is set toNonein the last iteration of the for loop,target=Nonewhen it prints inside off()Output:
>>> f.__code__.co_freevars ('target',) >>> import inspect >>> print(inspect.getclosurevars(f).nonlocals['target']) None
This might be made a bit clearer if we use a global variable rather than a free variable:
for target in ('a', 2, None): if isinstance(target, str): def f(): print(f'inside f(), {target=}') print(f'just created f(), {target=} at this point!')
Output.
just created f(), target='a' at this point! >>> print(target) None >>> f() inside f(), target=None >>> target = "whoa" inside f(), target='whoa'