About Modifying Globals
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Dec 4 21:09:54 EST 2014
LJ wrote:
> Hi All,
>
> I have a quick question regarding the modification of global variables
> within functions. To illustrate, consider the following toy example:
>
> a={"1": set()}
> b=9
>
> def gt(l):
> a["1"] = a["1"] | set([l])
The difference between this example and your second one:
> def gt2(l):
> b=b+l
is that the second is a "binding operation" and the first is not.
Binding operations include direct assignment to a name, deletions, imports
and a few other things:
b = 23
del b
import sys as b
are all considered binding operations, since they bind a value to a name
(or, in the case of del, unbind it). Inside functions, the compiler follows
the rule that any binding operation makes that variable a local for the
entire function, unless declared global.
So in the gt2() example, "b = b + 1" is interpreted as this:
- look up local variable b;
- add one to the result;
- assign it to local variable b.
which fails because b hasn't got a value yet.
This is different from, say, Lua, where that line would be interpreted as:
- look up local variable b;
- if that doesn't exist, look up global variable b instead;
- add one to the result;
- assign it to local variable b.
But that's not what Python does.
On the other hand, your first example doesn't include a direct assignment to
a name:
a["1"] = a["1"] | set([l])
looks like an assignment, but it's actually a method call! That is
approximately equivalent to:
a.__setitem__("1", X)
with X equal to the right hand side. Since that's a method call, it doesn't
count as a binding operation and the compiler doesn't treat a as a local,
it treats it as global, so the lookup on the right hand side succeeds, and
the method call modifies the set in place.
--
Steven
More information about the Python-list
mailing list