SystemError when defining
Joshua Landau
joshua.landau.ws at gmail.com
Fri Nov 4 15:10:00 EDT 2011
>
> >>> def x(nonlocal_var):
... def y():
... z = lambda *, keyword_only=nonlocal_var: None
... return y
...
>>> x(None)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in y
SystemError: no locals when loading 'nonlocal_var'
>>> dis.dis(x)
2 0 LOAD_CONST 1 (<code object y at
> 0x7f1fa5d57030, file "<stdin>", line 2>)
3 MAKE_FUNCTION 0
6 STORE_FAST 1 (y)
> 4 9 LOAD_FAST 1 (y)
12 RETURN_VALUE
>>> dis.dis(x(None))
3 0 LOAD_CONST 1 ('keyword_only')
3 LOAD_NAME 0 (nonlocal_var)
6 LOAD_CONST 2 (<code object <lambda> at
> 0x7f1fa626aa48, file "<stdin>", line 3>)
9 MAKE_FUNCTION 256
12 STORE_FAST 0 (z)
15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Conclusion:
When setting defaults to keyword-only arguments in lambdas which are inside
non-global scopes, cPython is unable to access *either the free variables
or global scope* and raises SystemError.
This is cool, though:
> >>> def y():
> ... global_var
> ... z = lambda *, keyword_only=global_var: None
> ...
> >>> y()
> >>>
>>> dis.dis(y)
> 2 0 LOAD_GLOBAL 0 (global_var)
> 3 POP_TOP
> 3 4 LOAD_CONST 1 ('keyword_only')
> 7 LOAD_GLOBAL 0 (global_var)
> 10 LOAD_CONST 2 (<code object <lambda> at
> 0x7f1fa5d4fd78, file "<stdin>", line 3>)
> 13 MAKE_FUNCTION 256
> 16 STORE_FAST 0 (z)
> 19 LOAD_CONST 0 (None)
> 22 RETURN_VALUE
>>> def x(nonlocal_var):
> ... def y():
> ... nonlocal_var
> ... z = lambda *, keyword_only=nonlocal_var: None
> ... return y
> ...
> >>> x(None)()
> >>>
What is happening is that LOAD_NAME is trying to access the value
'nonlocal_var' from y.__code__.co_freevars, but compilation doesn't push it
there from the lambda, so adding a call to it causes it to work. The change
of opcode implies that locality is decided before the opcodes are made,
and so not being pushed to co_freevars changes the opcode.
AKA:
*When setting defaults to keyword-only arguments in lambdas which are
inside non-global scopes, cPython doesn't push the name to co_freevars.*
Now - where shall I report this?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20111104/520e349d/attachment-0001.html>
More information about the Python-list
mailing list