Digression on Immutability of Strings
In Chapter 12, Strings
and Chapter 13, Tuples
we noted that string
s
and tuple
s are both immutable. They cannot be
changed once they are created. Programmers experienced in other
languages sometimes find this to be an odd restriction.
Two common questions that arise are how to expand a
string
and how to remove characters from a
string
.
Generally, we don't expand or contract a
string
, we create a new
string
that is the concatenation of the original
string
s. For example:
>>>
a="abc"
>>>
a=a+"def"
>>>
a
'abcdef'
In effect, Python gives us string
s of
arbitrary size. It does this by dynamically creating new
string
s instead of modifying existing
string
s.
Some programmers who have extensive experience in other languages
will ask if creating a new string
from the
original string
s is the most efficient way to
accomplish this. Or they suggest that it would be “simpler”
to allow mutable string
s for this kind of
concatenation. The short answer is that Python's storage management
makes this use if immutable string
s the simplest
and most efficient. We'll discuss this in some depth in the section called “Digression on Immutability of Strings”.
Responses to the immutability of tuple
s and
list
s vary, including some of the following
frequently asked questions.
- Q: Since
lists do everything
tuples do and are mutable, why bother with
tuples?
- Q: Wouldn't it be more
efficient to allow mutable
strings?
Q:
|
Since
list s do everything
tuple s do and are mutable, why bother with
tuple s?
|
A:
|
Immutable tuple s are more efficient
than variable-length list s. There are fewer
operations to support. Once the tuple is
created, it can only be examined. When it is no longer referenced,
the normal Python garbage collection will release the storage for
the tuple .
Many applications rely on fixed-length
tuple s. A program that works with
coordinate geometry in two dimensions may use 2-tuples to
represent (
x
,
y
)
coordinate pairs. Another example might be a program that works
with colors as 3-tuples,
(
r
,
g
,
b
),
of red, green and blue levels. A variable-length
list is not appropriate for these kinds of
fixed-length tuple.
|
Q:
|
Wouldn't it be “more
efficient” to allow mutable
string s?
|
A:
|
There are a number of axes for efficiency: the two most
common are time and memory use.
A mutable string could use less
memory. However, this is only true in the benign special case
where we are only replacing or shrinking the
string within a fixed-size buffer. If the
string expands beyond the size of the
buffer the program must either crash with an exception, or it must
switch to dynamic memory allocation. Python simply uses dynamic
memory allocation from the start. C programs often have serious
security problems created by attempting to access memory outside
of a string buffer. Python avoids this
problem by using dynamic allocation of immutable
string objects.
Processing a mutable string could use
less time. In the cases of changing a
string in place or removing characters from
a string , a fixed-length buffer would
require somewhat less memory management overhead. Rather than
indict Python for offering immutable
string s, this leads to some productive
thinking about string processing in
general.
In text-intensive applications we may want to avoid creating
separate string objects. Instead, we may
want to create a single string object --
the input buffer -- and work with slices of that buffer. Rather
than create string s, we can create
slice objects that describe starting and
ending offsets within the one-and-only input buffer.
If we then need to manipulate these slices of the input
buffer, we can create new string s only as
needed. In this case, our application program is designed for
efficiency. We use the Python string
objects when we want flexibility and simplicity.
|