myList = [5, 2]
def foo():
myList[0] = 6
In the example above, myList
is still mutated, though it is non-global and not passed in by parameter. This doesn't work however, if the variable is not a list.
myList = [5, 2]
def foo():
myList[0] = 6
In the example above, myList
is still mutated, though it is non-global and not passed in by parameter. This doesn't work however, if the variable is not a list.
The scope rules are roughly like this:
This is known as the LEGB rule.
In your case, it is because you are not assigning a value to the name myList
inside of foo()
. You are only assigning a value to the 0
index of an existing list. Therefore the global value of myList
is the scope you are using.
myList
is a global variable, though. It exists in the context of foo
, where you access and modify one of its elements.
myList = [0, 5]
def foo():
myList[0] = 6
print('Before foo: {}'.format(myList))
foo()
print('After foo: {}'.format(myList))
Output
Before foo: [0, 5]
After foo: [6, 5]
This doesn't work however, if the variable is not a list.
I assume that you tried something similar to the following:
a = 0
def bar():
a = 6
print('Before bar: {}'.format(a))
bar()
print('After bar: {}'.format(a))
Output
Before bar: 0
After bar: 0
In this case, you don't observe any change in the global variable a
because within bar
you're assigning to a new local variable a
which shadows the global variable of the same name. You set the local variable a
to 6, which has no effect as the variable is discarded as soon as the function ends.
You can show that even simple integers declared in the global scope can be accessed within function scopes by running something like the following. In this case, we specify that the function should modify an existing global variable b
rather than assigning to a new local one.
b = 0
def baz():
global b
b = 6
print('Before baz: {}'.format(b))
baz()
print('After baz: {}'.format(b))
Output
Before baz: 0
After baz: 6