Richard Damon wrote: > On 9/19/19 6:16 AM, Eko palypse wrote: >>> In all cases, if the optional parts are omitted, the code is executed in >>> the current scope. ... >>> >>> >>> You can see from it that "globals" is optional. >>> And that, if "globals" is missing, then >>> "exec" is executed in the current scope ("f1" in your case). >> Thank you for your answer, and that is exactly what confuses me? >> Where does x come from? If I only would read x then I would understand >> why it can be found/read but I alter it and as such I either have to >> provide the info that this is a global variable, declare it inside of f1 >> or provide the globals dict to exec. But I don't do any of it. Why is >> exec able to use the global x? >> >> Eren > > I think the issue is that x += 1 isn't exactly like x = x + 1, and this > is one case that shows it. x = x + 1 is an assignment to the symbol x, > which makes x a local, and thus the read becomes an undefined symbol. x > += 1 is different, it isn't a plain assignment so doesn't create the > local. The read of x is inherently tied to the writing of x so x stays > referring to the global.
I think you are wrong; both x += 1 and x = x + 1 turn x into a local variable: >>> def f(): ... x += 1 ... >>> x = 42 >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'x' referenced before assignment >>> def g(): ... x = x + 1 ... >>> g() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in g UnboundLocalError: local variable 'x' referenced before assignment The difference is that x = x + 1 is evaluated as x = x.__add__(1) while x += 1 becomes x = x.__iadd__(1) For mutable x this allows modifying x in place with consequences likely to surprise when you see it for the first time: >>> t = ["Nobody expects "], >>> t[0] = t[0] + ["the Spanish inquisition"] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> t (['Nobody expects '],) The above creates a new list which cannot become the first item of the (immutable) tuple. >>> t[0] += ["the Spanish inquisition"] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment The above changes the first item of the tuple in place, but afterwards the attempt to rebind t[0] still fails. -- https://mail.python.org/mailman/listinfo/python-list