String Immutability in Python and Why It Matters More Than You Think
DEV Community

String Immutability in Python and Why It Matters More Than You Think

The Illusion of Modification

Strings cannot be modified in place. Understanding the implications changes how you reason about string-heavy code. Python strings are immutable. This is stated in every introductory tutorial and genuinely understood by relatively few developers.

Immutability does not just mean "you cannot change a string." It means every string operation that appears to modify a string is actually creating a new string object. This has performance implications, mutation implications, and produces interview questions that trip up developers who have never thought carefully about what immutability means in practice.

s = "hello"
print(id(s))
s = s.upper()
print(id(s))
s = s + " world"
print(id(s))

Output - three different memory addresses:

140234567890
140234567950
140234568010

Each operation creates a new string object. The name s is rebound to the new object. The original strings become eligible for garbage collection.

String Concatenation in Loops

result = ""
for word in ["Python", "is", "fast"]:
    result += word + " "
print(result.strip())

This works correctly but has a performance problem. Each += creates a new string object. For a loop with 1000 iterations this creates 1000 intermediate string objects.

The efficient pattern:

words = ["Python", "is", "fast"]
result = " ".join(words)
print(result)

str.join() allocates the final string in one operation. For large sequences this is significantly faster.

The Mutation That Is Not Mutation

s = "hello world"
s.replace("hello", "goodbye")
print(s)

Output: hello world

.replace() does not modify s. It returns a new string. This surprises developers who are used to methods modifying objects in place (like list.append()). String methods always return new strings.

The fix:

s = s.replace("hello", "goodbye")
print(s)

Interview Problem

def process(text):
    text = text.strip()
    text = text.lower()
    text = text.replace(" ", "_")
    return text

original = " Hello World "
result = process(original)
print(original)
print(result)

Output:

 Hello World 
hello_world

Each operation inside process creates a new string and rebinds the local name text. The original variable in the calling scope still points to the original string object, which is unchanged because strings are immutable.

String Interning

a = "hello"
b = "hello"
c = "hello world"
d = "hello world"
print(a is b)
print(c is d)

Output:

True
False

Python interns short strings that look like valid identifiers. Both a and b point to the same interned string object. Longer strings or strings with spaces are not automatically interned, so c and d may be different objects despite having equal values. Use == for string equality comparisons. Never use is.

Understanding string immutability is foundational to reasoning about string-heavy code correctly. Practice string tracing problems at pycodeit.com.

Comments

No comments yet. Start the discussion.