I have a function called letthat changes the namespace of callers to insert a new variable.
def let(**nameValuePair):
from inspect import stack
name, value = nameValuePair.items()[0]
stack()[1][0].f_locals[name] = value
return value
The idea is that you can insert assignment operators anywhere, even if assignment statements are usually not allowed in Python (although let()5 extra characters are required.
This works great when called from a global namespace.
>>> let(outside = 'World')
>>> print(outside)
World
This does not fail NameError: global name 'hello' is not defined:
>>> def breaker():
... let(hello = 'World')
... print(hello)
...
>>> breaker()
You can come to the conclusion that the problem is related to my function let. It is not - my function works fine. To show you that:
>>> def fine():
... let(another = 'World')
... print(locals()['another'])
...
>>> fine()
World
, Python breaker. , , , breaker, let, dis.
>>> def normal():
... hello = 'World'
... print(hello)
...
>>> normal()
World
>>> from dis import dis
>>> print(dis(normal))
0 LOAD_CONST 1 ('World')
3 STORE_FAST 0 (hello)
6 LOAD_FAST 0 (hello)
9 PRINT_ITEM
10 PRINT_NEWLINE
11 LOAD_CONST 0 (None)
14 RETURN_VALUE
>>> print(dis(breaker))
0 LOAD_GLOBAL 0 (let)
3 LOAD_CONST 1 ('hello')
6 LOAD_CONST 2 ('World')
9 CALL_FUNCTION 256
12 POP_TOP
13 LOAD_GLOBAL 2 (hello)
16 PRINT_ITEM
17 PRINT_NEWLINE
18 LOAD_CONST 0 (None)
19 RETURN_VALUE
, breaker, , hello , .
? , , , , , :
LOAD_GLOBAL 1 (locals)
CALL_FUNCTION 0
LOAD_CONST 1 ('hello')
BINARY_SUBSCR
, , , . :
... , , STORE_GLOBAL DELETE_GLOBAL RETURN_VALUE, ? - - ?