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. -- https://mail.python.org/mailman/listinfo/python-list