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()
2 Answers 2
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
.
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.
-
Sorry,I have removed the global tag with c in my code. Why c can not be changed with global or nonlocal but mutable obejects can? Thank you, I'm a new hand in python.Pengfei Xu– Pengfei Xu05/06/2022 14:40:28Commented May 6, 2022 at 14:40
-
By removing
global c
from your original question, you've made it an entirely different question, and you'll find it doesn't work anymore. The reasons why are outlined in this answer.AKX– AKX05/06/2022 14:41:59Commented May 6, 2022 at 14:41
4
so clearlyc
was changed. (Of course you cannot change the number 3 itself but you can change variables containing that value.)