No, it’s not a paradox or a contradiction. The tuple is immutable and you can’t change it after it is defined, but the need to modify a tuple, and other immutable sequences, is a common one. This sometimes worries beginners, but changing immutable data is very easy – you simply create a new data object with the desired elements. For example, if you want to delete the ith element of a tuple you would use
u = t[:i]+t[i+1:]
You can see that u is a new tuple built by concatenating two slices of t. Clearly t is still immutable, but if you write:
t = t[:i]+t[i+1:]
it does look as if t has been changed. What has happened, of course, is that t is set to reference the new tuple and the original tuple that t references will be garbage collected as long as there is no other variable referencing it.
Similarly if you want to add an element to a tuple you can use:
t = t[:i]+(42,)+t[i+1:]
where in this case you need to use a trailing comma to create a tuple with one element.
In general, to manipulate a tuple, or any immutable data structure, you simply take the data apart and then put it back together to create a new data structure, see String Manipulation in the next chapter for more examples.
In chapter but not in this extract
Tuples
Modifying Immutable Sequences
Destructuring
Sorting & Order
Ranges
Summary
A sequence isn’t like a data type encountered in other languages. It is more a mixin that can be added to or found in a range of different data types.
The archetypal sequence is the list, closely followed by the tuple.
All sequences can be indexed and sliced.
Indexing selects a particular element of the sequence and if it doesn’t exist throws an exception.
Slicing extracts or modifies a subsequence and never throws an exception.
Sequences also support a range of useful methods including in which can test to see if an object is part of a sequence.
A tuple is an immutable list.
Even though a tuple is immutable it can appear to be modified by creating new tuples derived from existing tuples.
A sequence is always an iterable
Destructuring can be used to access the elements in a list, tuple or, in general, any iterable.
Being able to sort its element is specific to lists and tuples.
The range sequence is a functional implementation of a sequence and is useful whenever you need to create an integer sequence.