Am Donnerstag, 19. September 2019 20:24:49 UTC+2 schrieb Peter Otten: > 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.
Thank you very much, really, very much appreciated. Normally I do use docs.python.org as my first resource to look for an answer to my questions but I'm not always convinced that my understanding/interpretation is correct. Then I research on the web to see if there are similar questions and try to understand these explanations but ... and in this particular case I wasn't even able to find an answer. The dis module is nice to see differences but I assume more useful to software developers than to hobby programmers like me. At least not in the current state of knowledge I have. I was under the impression that I have a good understanding of the python language before I started my current project but now ... Enough whining :-) Once again, Thank you very much Eren -- https://mail.python.org/mailman/listinfo/python-list