Guide Python Intermediate

9.14 Common Mistakes

The most common string bugs in Python -- expecting a method to mutate in place, mismatching find() and index() error behavior, off-by-one slicing errors, and O(n^2) concatenation in a loop.

3 min read

Assuming a Method Mutates in Place

Every string method returns a new string — the original is never changed, since str is immutable (see 9.1 Introduction to Strings).

>>> s = "hello"
>>> s.upper()          # returns a new string
>>> s                  # s itself is UNCHANGED
'hello'
>>> s = s.upper()      # must reassign to actually keep the result

Confusing find() and index()

find() returns -1 when nothing matches; index() raises ValueError. Using the wrong one for the situation either silently produces a bogus -1 result or crashes unexpectedly.

>>> "hello".find("z")      # no exception -- easy to silently misuse
-1
>>> "hello".index("z")     # raises instead
Traceback (most recent call last):
ValueError: substring not found

Off-by-One Slicing Errors

Forgetting that stop in s[start:stop] is exclusive is one of the most common slicing bugs — s[0:5] gets 5 characters (indices 0–4), not 6.

O(n²) Concatenation in a Loop

Building a large string with += inside a loop looks harmless on small inputs but degrades badly at scale — see 9.11 Memory and Performance for why, and join() for the fix.

# Looks fine on 10 items, degrades badly on 100,000
result = ""
for line in lines:
    result += line

Comparing Strings with is

Interning is a CPython implementation detail, not a guarantee — comparing with is can pass in a quick test and fail unpredictably on runtime-built strings.

>>> a = "hello"
>>> b = "".join(["h", "e", "l", "l", "o"])
>>> a == b       # correct: compares content
True
>>> a is b       # WRONG tool: compares identity, not guaranteed True
False

Quick Interview Answer

“The recurring string bugs share one root cause or another: forgetting immutability means a method’s return value must be captured (s = s.upper(), not just s.upper()); mixing up find()’s silent -1 with index()’s ValueError produces either a bogus result or an unexpected crash; forgetting slicing’s stop is exclusive causes off-by-one errors; building a large string with += in a loop is O(n²) and only shows up as a real problem at scale; and comparing with is instead of == relies on CPython’s interning, which isn’t a language guarantee.”

Common Mistakes

  • Writing s.strip() on a line and expecting s itself to be stripped afterward — the call must be assigned back: s = s.strip().
  • Using find()’s -1 return value directly as an index without checking for it first, silently slicing from the end of the string instead of failing loudly.
  • Reaching for += string-building inside a loop that turns out to run over a large or unbounded number of iterations (a log file, an API pagination loop) — the O(n²) cost compounds fast.

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form