Why changing global does not give error?
Why on earth Python lets change not global declared list in function?
RE-UPDATED
numbers = []
num = 4
def add(n, thisnum=None):
# changing global list without global declaration!
numbers.append(n)
if thisnum:
num = thisnum
print 'num assigned', thisnum
##numbers = ('one', 'two', 'three')
## adding this line makes error:
"""Traceback (most 开发者_如何学Gorecent call last):
File "J:\test\glob_vals.py", line 13, in <module>
add(i)
File "J:\test\glob_vals.py", line 6, in add
numbers.append(n)
UnboundLocalError: local variable 'numbers' referenced before assignment
"""
for i in (1,2,3,564,234,23):
add(i)
print numbers
add(10, thisnum= 19)
# no error
print num
# let the fun begin
num = [4]
add(10, num)
print num
# prints:
"""[1, 2, 3, 56, 234, 23]
num assigned 19
4
num assigned [4]
[4]
"""
If I put assignement to variable with same name then the action before that line becomes error, not the added line (byte code compiler spots it, I guess).
You aren't assigning to the global variable, you are calling a method on it which changes its contents. This is allowed.
What you can't do without the global
keyword is this:
def add(n):
#global numbers
numbers = numbers + [n]
Result:
Traceback (most recent call last): File "C:\Users\Mark\Desktop\stackoverflow\python\test.py", line 8, in add(i) File "C:\Users\Mark\Desktop\stackoverflow\python\test.py", line 5, in add numbers = numbers + [n] UnboundLocalError: local variable 'numbers' referenced before assignment
The difference is that here I am not mutating the existing list - I'm trying to create a new list and reassign back to the global scope. But this cannot be done without the global
keyword.
Regarding your update:
The following line is OK because it creates a new local name num
in the scope of the function. This does not affect the value of the variable at the global scope.
num = thisnum
global x
only affests x = ...
(namely, it makes this re-assign the global x
instead of creating an independent local x
). It doesn't affect x.member = ...
(because that's a method call) or x.mutating_method(...)
, because Python (this is not an issue of static vs. dynamic, btw) can't know (and doesn't care) that these method modify self
in some way - so you'd have to prevent method calls on (objects pointed to by) global variables ... which is, of course, pointless.
Regarding update:
When you do num = thisnum
, you are doing something completely different from numbers.append(n)
- you are creating a local variable (because you didn't declare global num
) and assigning it some value. This never even touches the global num
.
Because you are just appending to a list.
Accessing and assigning are different concepts. When you append a list, you are just calling a method which changes its value. Supposing you did +=
, that would be assigning.
If you were to do this:
>>> numbers = []
>>> def add(n):
numbers += n
>>> n = [1, 2]
>>> add(n)
It would fail because this is assignment.
To fix this, in the add()
function, you add:
>>> def add(n):
global numbers
numbers += n
精彩评论