str.replace()
Return a copy of the string with all occurrences of substring old replaced by new.
Common call
"hello".replace("l", "L")
Returns
new str — the original is unchanged
Replaces
all occurrences unless count is given
Watch out
case-sensitive; no regex — use re.sub for either
str.replace(oldold — The substring to search for. If empty, insertion behavior applies (see Pitfalls).type: str · required, newnew — The substring to substitute. May be empty to delete matches.type: str · required, countcount — Maximum number of replacements. Negative or omitted means replace all.type: int · default: -1=-1)
→ str
Demo
Live evaluation
Try:
Inputs
stringstrthe source
oldstrto find
newstrreplacement
countint-1 = all
Output
'hello world'.replace('o', '0')
'hell0 w0rld'
str.replace() returns a new string in which every occurrence of old has been replaced by new. The original string is unchanged. If count is given, only the first count occurrences are replaced.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| old | str | yes | The substring to search for. If empty, insertion behavior applies (see Pitfalls). |
| new | str | yes | The substring to substitute. May be empty to delete matches. |
| count | int | no (-1) | Maximum number of replacements. Negative or omitted means replace all. |
Return value
str — A new string with the substitutions applied. If old is not found, the returned string equals the original.
Common patterns
Chained replacements
Sanitize text by replacing several problematic characters in sequence.
# normalize a slug slug = title.replace(" ", "-").replace("_", "-").lower()
Removal via empty new
Passing an empty string as new deletes every occurrence of old.
phone.replace("-", "").replace(" ", "") # '5551234567' from '555-123 4567'
Templating without f-strings
Useful when the template comes from a config file at runtime.
template = "Hello, {name}! You have {n} messages." msg = template.replace("{name}", "Alex").replace("{n}", str(3))
Examples
1. Replace all occurrences
"hello world".replace("o", "0")
Returns
'hell0 w0rld'2. Replace only the first occurrence
"aaaa".replace("a", "b", 1)
Returns
'baaa'3. Delete substring by replacing with empty
"a-b-c".replace("-", "")
Returns
'abc'4. Substring not present — original returned
"hello".replace("z", "Z")
Returns
'hello'Pitfalls
1. The original string is not modified
Strings are immutable. s.replace(...) returns a new string; if you don’t assign the result, nothing changes.
Wrong
s = "hello" s.replace("l", "L") print(s)
hello
Fix
s = "hello" s = s.replace("l", "L") print(s)
heLLo
2. Empty old inserts between characters
Passing "" for old doesn’t no-op — it inserts new at every position.
Surprising
"abc".replace("", "-")
'-a-b-c-'
Guard
if old: s = s.replace(old, new)
'abc' (guarded)
3. Case-sensitive only
No case-insensitive flag exists. Reach for re.sub with re.IGNORECASE.
Misses "Hello"
"Hello hello".replace("hello", "hi")
'Hello hi'
Fix
import re re.sub("hello", "hi", s, flags=re.I)
'hi hi'
When to use
Use it
- Literal substring — no pattern needed
- Same case as source
- Small number of distinct replacements (chain them)
- Performance-critical hot loop — it’s the fastest option
Reach for something else
- Need regex → re.sub
- Case-insensitive → re.sub(..., flags=re.I)
- Many replacements at once → str.translate
- Unicode normalization → unicodedata.normalize first
Notes
Complexity
O(n) — single pass over the source
Return
new str — source untouched
CPython impl
Objects/unicodeobject.c :: unicode_replace
Memory
Allocates a fresh buffer sized to the result
Thread-safe
Yes — str is immutable
FAQ
Pass 1 as the third argument.
"aaaa".replace("a", "b", 1) # 'baaa'
History
3.9
No changes to str.replace. Related: str.removeprefix and str.removesuffix added.
2.0
Method introduced with the unified string type.