Please see the following code:
def good():
foo[0] = 9 # why this foo isn't local variable who hides the global one
def bad():
foo = [9, 2, 3] # foo is local, who hides the global one
for func in [good, bad]:
foo = [1,2,3]
print('Before "{}": {}'.format(func.__name__, foo))
func()
print('After "{}": {}'.format(func.__name__, foo))
The result is as below:
# python3 foo.py
B开发者_开发问答efore "good": [1, 2, 3]
After "good": [9, 2, 3]
Before "bad" : [1, 2, 3]
After "bad" : [1, 2, 3]
Because you're not setting foo, you're getting something in foo (foo[0] to be exact).
In bad
you create a new variable foo
. In good
you do something like foo.set(0, 9)
(set item 0 to value 9). Which is using a variable, and not defining a new name.
Variables will look to their inner scope first then to outer scopes in python. For instance:
FOO = 'global'
def printfoo():
print FOO
# prints 'global'
def printfoolocal():
FOO = 'local'
print FOO
# prints 'local'
If you'd like to modify a globally scoped variable, you need to use the global
keyword
def modifyfoo():
global FOO
FOO = 'modified'
print FOO
# prints 'modified'
To make simple, python first look in the local variables and after in the global ones. (For reading or for creating a variable)
So, in good, you take the foo variable : No local foo variable and a global foo variable => you take the global one and you modify it.
In bad, you create a new (local) variable, so the global one is not modified.
You can specify that a variable is global with the global keyword :
def good2():
global foo
foo = [9, 2, 3]
If, like good, you want to replace the contents of the list foo, then you could assign to a slice of the whole list like:
def good2():
foo[:] = [9, 2, 3]
Just like where good
assigned to one element of the list, this replaces the whole contents.
In bad
you were binding a new list to the name foo.
精彩评论