While reviewing gh-120906: Support arbitrary hashable keys in FrameLocalsProxy by encukou · Pull Request #122309 · python/cpython · GitHub I noticed that dis.show_code
doesn’t clearly distinguish the hidden local variables added for inlined module level comprehensions from the regular local variables.
>>> dis.show_code("[x for x in range(10)]")
Name: <module>
Filename: <disassembly>
Argument count: 0
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals: 1
Stack size: 4
Flags: 0x0
Constants:
0: 10
Names:
0: range
Variable names:
0: x
>>> def f():
... return [x for x in range(10)]
...
>>> dis.show_code(f)
Name: f
Filename: <python-input-13>
Argument count: 0
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals: 1
Stack size: 4
Flags: OPTIMIZED, NEWLOCALS
Constants:
0: None
1: 10
Names:
0: range
Variable names:
0: x
The fact x
is a hidden iteration variable in the first case is kinda implied by the missing OPTIMIZED
and NEWLOCALS
flags on the overall code object, but when it comes to other differences like free and cell variables we make the differences much more pronounced:
>>> def outer():
... x = 1
... def inner():
... return x
... return inner
...
>>> dis.show_code(outer)
Name: outer
Filename: <python-input-8>
Argument count: 0
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals: 1
Stack size: 2
Flags: OPTIMIZED, NEWLOCALS
Constants:
0: None
1: 1
2: <code object inner at 0x7ffa31807020, file "<python-input-8>", line 3>
Variable names:
0: inner
Cell variables:
0: x
>>> dis.show_code(outer())
Name: inner
Filename: <python-input-8>
Argument count: 0
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals: 0
Stack size: 1
Flags: OPTIMIZED, NEWLOCALS, NESTED
Constants:
0: None
Free variables:
0: x
I’m leaning towards “local variables being defined in a code object that doesn’t otherwise use local variables” being a sufficiently clear indicator in the output, but I’m uncertain enough of that conclusion that it seemed worthwhile to post about it here and see if anyone else thought it might be worth trying to improve the way dis.show_code
presents these cases.