Why mutable objects like array or list can be visited and changed in function directly while immutable objects like number can be only visited but not changed? What is the mechnism. Below is some simple test code.
import numpy as np
a = [1,2,3]
b = np.array([1,2,3])
c = 3
def func():
a.append(1)
b[0] = 2
c = 1
print(c)
func()
CodePudding user response:
The difference is whether you assign or mutate. When you mutate data, like with a.append(1)
, the object reference (a
) is not changed: it is still the same list reference. When you assign, the variable really gets a different reference, and the object that was previously referenced does not get affected.
Without global
, globals can be mutated (when they are mutable), but not assigned.
This has little to do with mutable or not, as even a = []
would not be allowed without the corresponding global
statement. Even though lists are mutable, this a = []
is not attempting to mutate anything. It assigns. And that requires global
.
CodePudding user response:
Well, you're kind of answering your own question.
Mutable objects are internally mutable, while immutable objects, well, aren't.
The global c
(or nonlocal c
in an inner function) statement tells Python that the name c
refers to the name c
in the global (or outer) scope.
Since integers aren't internally mutable (and don't implement __iadd__
, the magic method that could back =
), c = 1
does c = c 1
, i.e. assigns the value of the expression c 1
to the global name c
.
If you attempt c = 1
in a function without the global
statement, you'll get an UnboundLocalError
, since there is no name c
to access and increment before that assignment itself.
This stands for any name; trying to do
>>> a = []
>>> def f():
... a = a ["foo"]
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
UnboundLocalError: local variable 'a' referenced before assignment
also fails, since a
has not been assigned within the function.