[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()
[1]
>>> 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.

HTH

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




More information about the Tutor mailing list