Pregunta

I have a question about global variables in python. If I got this correctly, all variables that I define in my class can be read from each method in this class. Now I thought that I could only write into the global variables if I mark them with global 'variableName' before. But here is what freaks me out:

def foo(a):
    for i in range(a[0].__len__()):
        a[0][i] -= a[1][i]
a = [[0,1,2,3,4,5,6],[0,1,2,3,4,5,6]]
foo(a)
print(a)

gives me

[[0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6]]

But WHY? I mean, I never decleared 'global a'.

Strange thing is, if i do:

def foo(a):
    a -= 1
a = 2
foo(a)
print(a)

Why does this give me

2

I don't understand the difference :/

¿Fue útil?

Solución

You have a problem with your function definitions. You are passing both functions an argument, thus making it unnecessary to declare anything global in the first place. If you would remove the arguments from your definitions, this question would make a little more sense.

The whole confusion here lies within mutability of data types in python. Lists and dictionaries are mutable containers, which means that their values can be changed at any time. Other data types, like integers, floats, tuples and so on are immutable. You cannot change them. You can create new ones, like 1 + 1 will return a new integer 2.

In your first example, you're modifying the contents of a list. Lists are mutable containers which means that their contents can change. If you happen to have a in the global scope, then a function in that same scope can modify the contents of the list.

def foo():
    """ Notice i've removed the argument `a` from the function def, to illustrate my point.. """
    for i in range(a[0].__len__()):
        a[0][i] -= a[1][i]
>>> a = [[0,1,2,3,4,5,6],[0,1,2,3,4,5,6]]
>>> foo()
>>> print(a)
[[0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6]]

In your second example, you're modifying an integer. Integers are immutable data types and cannot be modified. The following will modify the variable a (by creating a new integer) in the local scope of function foo() but because you have not defined a global or return the local a, there's no visible change.

def foo(a):
    a -= 1
>>> a = 2
>>> foo(a)
>>> print(a)
2

Otros consejos

TL;DR global is not about mutability.

You're passing a list to the function as the argument a. A list is mutable, so the function can change it. The fact that the argument and the global are both called a is immaterial:

def foo(some_list):
    some_list.append('foo!')

global_list = []

foo(global_list)
print(global_list)

prints ['foo!'] even though foo doesn't reference global_list directly. The same is happening in your code.

Now more to the point wrt. modifying globals:

def bar():
    global_list.append('bar.')

will also modify global_list, because when it looks up the symbol "global_list" it finds it in the module ("global") scope. The only case where you need the global keyword is when you want to rebind the name global_list, because in

def reset():
    global_list = []

the assignment implicitly creates a local variable global_list, so it should be written

def reset():
    global global_list
    global_list = []
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top