[Tutor] scope of a global dictionary?

Karl Pflästerer sigurd at 12move.de
Fri Feb 6 17:40:07 EST 2004

On  6 Feb 2004, Marilyn Davis <- marilyn at deliberate.com wrote:

> My understanding is that a global variable can be accessed, but not
> altered in a function's code block, unless the global declaration is
> used:

That's not entirely true.

> x = 3
> def f():
>     print x       <-  is ok

No binding of a name

> def g():
>     x += 1        <-  not ok

Here x gets bound to x+1.

> def h():
>     global x
>     x *= 2        <-  ok again

Here you declared x global.  That short circuits the name resolving.

> But I wrote this little dictionary example and it doesn't need the
> global declaration to add new entries to the dictionary.

Yes and no :-)

>         dict[word.lower()] = meaning

Here again; you don't bind the name dict to a new value.

A small example to make it clearer:
>>> lst = [1]
>>> def f (): return lst
>>> def g():
...     lst.append(1)
...     return f()
>>> def h(): lst = lst + lst
>>> f()
>>> g()
[1, 1]
>>> h()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 1, in h
UnboundLocalError: local variable 'lst' referenced before assignment

So g() caused no problems but could change the value of lst.  What is
the difference to h()?  In h() we made an assignment operation and
assignment statements *bind* names.  Now `lst' was the `lst' in the
local function scope and no longer an arbitrary name which could be
searched in the surrounding environment (or __builtin__).

That whole issue is not trivial; if you want to know more about it read
e.g. Pep 227 (which describes the lexical (statical) scoping rules and
explains also these subtilities; furthermore you could read in the
Python reference about `Naming and Binding' (in the section `Execution
model').  On example from the Pep which shows a problem which can arise 

,----[ pep 227 ]
| An example from Tim Peters demonstrates the potential pitfalls of
|     nested scopes in the absence of declarations:
|     i = 6
|     def f(x):
|         def g():
|             print i
|         # ...
|         # skip to the next page
|         # ...
|         for i in x:  # ah, i *is* local to f, so this is what g sees
|             pass
|         g()
|     The call to g() will refer to the variable i bound in f() by the for
|     loop.  If g() is called before the loop is executed, a NameError will
|     be raised.

Since `i' gets bound in the function declaration (the for loop bounds
also) a similar problem like yours happens.


Please do *not* send copies of replies to me.
I read the list

More information about the Tutor mailing list