DEV Community

Cover image for String Immutability in Python and Why It Matters More Than You Think
Ameer Abdullah
Ameer Abdullah

Posted on

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

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.


The Illusion of Modification

s = "hello"
print(id(s))

s = s.upper()
print(id(s))

s = s + " world"
print(id(s))
Enter fullscreen mode Exit fullscreen mode

Output — three different memory addresses:

140234567890
140234567950
140234568010
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Output:

  Hello World  
hello_world
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Output:

True
False
Enter fullscreen mode Exit fullscreen mode

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.


Top comments (0)