exec and globals and locals ...
Peter Otten
__peter__ at web.de
Thu Sep 19 14:24:21 EDT 2019
Eko palypse wrote:
> Am Donnerstag, 19. September 2019 18:31:43 UTC+2 schrieb Peter Otten:
>> Eko palypse wrote:
>>
>> > No, I have to correct myself
>> >
>> > x = 5
>> > def f1():
>> > exec("x = x + 1; print('f1 in:', x)")
>> > return x
>> > print('f1 out', f1())
>> >
>> > results in the same, for me confusing, results.
>> >
>> > f1 in: 6
>> > f1 out 5
>>
>> Inside a function exec assignments go to a *copy* of the local namespace.
>> Also LOAD_NAME is used to look up names. Therefore you can read and then
>> shade a global name with its local namesake.
>>
>> Inside a function the namespace is determined statically. As f1() has no
>> assignment to x (code inside exec(...) is not considered) x is looked up
>> in directly the global namespace using LOAD_GLOBAL.
>>
>> If you want to access the local namespace used by exec() you have to
>> provide one explicitly:
>>
>> >>> x = 5
>> >>> def f():
>> ... ns = {}
>> ... exec("x += 1", globals(), ns)
>> ... return ns["x"]
>> ...
>> >>> f()
>> 6
>> >>> x
>> 5
>>
>> By the way, in Python 2 where exec was a statement the local namespace is
>> shared:
>>
>> >>> x = 5
>> >>> def f():
>> ... exec "x += 1"
>> ... return x
>> ...
>> >>> f()
>> 6
>> >>> x
>> 5
>
> Sorry, missed that.
> Thank you, may I ask you how I could have come myself
> to that explanation? What do I have to read to get that understanding?
> Hopefully you don't say read the C code, because that is something
> I tried but failed miserably.
https://docs.python.org/3/library/functions.html#exec
https://docs.python.org/3/reference/executionmodel.html#naming-and-binding
(I had to google for the second link.)
I usually experiment with code and the disassembler. I find its output quite
readable,
>>> def f(): x += 1
...
>>> import dis
>>> dis.dis(f)
1 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (x)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis.dis(compile("x += 1", "<nofile>", "exec"))
1 0 LOAD_NAME 0 (x)
3 LOAD_CONST 0 (1)
6 INPLACE_ADD
7 STORE_NAME 0 (x)
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
and you can limit yourself to small snippets.
More information about the Python-list
mailing list