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