In Python, lists are passed by reference to functions. If that is so, what's happening here?
>>> def f(a):
... print(a)
... a = a[:2]
... print(a)
...
>>> b = [1,2,3]
>>> f(b)
[1, 2, 3]
[1, 2]
>>> print(b)
[1, 2, 3]
>>>
Indeed the objects are passed by reference but a = a[:2]
basically creates a new local variable that points to slice of the list.
To modify the list object in place you can assign it to its slice(slice assignment).
Consider a
and b
here equivalent to your global b
and local a
, here assigning a
to new object doesn't affect b
:
>>> a = b = [1, 2, 3]
>>> a = a[:2] # The identifier `a` now points to a new object, nothing changes for `b`.
>>> a, b
([1, 2], [1, 2, 3])
>>> id(a), id(b)
(4370921480, 4369473992) # `a` now points to a different object
Slice assignment work as expected:
>>> a = b = [1, 2, 3]
>>> a[:] = a[:2] # Updates the object in-place, hence affects all references.
>>> a, b
([1, 2], [1, 2])
>>> id(a), id(b)
(4370940488, 4370940488) # Both still point to the same object
Related: What is the difference between slice assignment that slices the whole list and direct assignment?