Python passes by object. In change_list1
, you pass a mutable object, and mutate it. It's the same object (a list), just altered (content changed). mylist
is a local parameter that refers to the object. The function returns the original object. You'll find that his_list
is altered as well because it refers to the same object.
In change_list2
, you also pass a mutable object, but instead of mutating it, you assign a new object to the local parameter. The original object is unchanged. The function returns the new object.
It's helpful to think of variables in Python as just names of objects. When you pass parameters to a function, the names of the parameters in the function are just new names for the original objects passed into the function.
You can see this by printing the IDs of the object names passed into the function, and the IDs of the object names of the parameters:
a = [1,2,3] # mutable object (content can be altered)
b = 1 # immutable object (content can't be altered).
print(f'id(a) = {id(a)}, id(b) = {id(b)}')
def func(c,d):
print('INSIDE func')
print(f'id(c) = {id(c)}, id(d) = {id(d)}')
c.append(4) # mutable object can be altered.
d = 4 # local name 'd' assigned a new object.
print('AFTER altering c & d')
print(f'id(c) = {id(c)}, id(d) = {id(d)}')
return c,d
e,f = func(a,b)
print('AFTER func called')
print(f'id(a) = {id(a)}, id(b) = {id(b)}')
print(f'id(e) = {id(e)}, id(f) = {id(f)}')
print(f'a = {a}, b = {b}')
print(f'e = {e}, f = {f}')
Output:
id(a) = 2290226434440, id(b) = 1400925216
INSIDE func
id(c) = 2290226434440, id(d) = 1400925216
AFTER altering c & d
id(c) = 2290226434440, id(d) = 1400925312
AFTER func called
id(a) = 2290226434440, id(b) = 1400925216
id(e) = 2290226434440, id(f) = 1400925312
a = [1, 2, 3, 4], b = 1
e = [1, 2, 3, 4], f = 4
Note that the IDs of a
and b
coincide with parameter names c
and d
. The names refer to the same objects.
c
object gets mutated. a
refers to the same object, so will show the same change.
d
object is immutable. There are no methods like .append
to alter the object's content. d
can only be reassigned. It gets reassigned and shows a new ID. b
object is unchanged.
After the function call e
becomes a new name for the object named c
(also named a
). Name c
no longer exists. It was a local function name. f
becomes a new name for object d
(integer 4) and d
no longer exists. b
is unaffected and references the original integer 1.
a
and e
refer to the original, but mutated object. b
and f
refer to different, immutable objects.