Tyler D
Tyler D

Reputation: 333

Altering an immutable object?

def add_alpha(tuple_in):
    list_out = []
    for t in tuple_in:
        t.append(10)
        
a = ([1,1], [2,2], [3,3])
b = a
print(id(a), id(b))
add_alpha(a)
print(id(a), id(b))
print(b)

The above example shows that, even though a is an immutable object, we can technically alter its elements. How is that so? Wouldn't it make more sense if a was assigned a new id, so that we are not changing b as well?

Upvotes: 0

Views: 137

Answers (1)

timgeb
timgeb

Reputation: 78690

There are two separate misconceptions here.

Tuples can have mutable elements

a is immutable with respect to which lists a[0], a[1] and a[3] point to.

In other words

l = a[0]
# do something (that does not reassign a)
print(l is a[0]) 

will always print True.

However, you can still mutate a[0]. A list cannot know that it is in some tuple and shall now be resistant to mutations.

If you issued

l = [1, 2, 3]
t = (l, 'foo')

you would expect l.append(1) to work fine. (And it does.)

Assignment never copies data

Python names work like labels for objects in memory. Assigning another name creates a new label, nothing more. When you issue

a = Foo() # some mutable object, or with mutable elements
b = a
mutate(a) # mutate a or one of its elements

the change will be seen across all names (a and b), because there only ever was one mutable object in memory. a = b didn't copy anything.

Upvotes: 1

Related Questions