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