To remove a character from a string in Python, you build a new string without it. Which method you want depends on whether you know the position or the character:
text[:i] + text[i+1:] # remove the character at index i
text.replace("x", "") # remove every "x"
text.replace("x", "", 1) # remove only the first "x"
There is no del and no item assignment. Both raise a TypeError, which is the first thing to understand here.
Every result below is a real run on Python 3.12.5.
Removing a character by index
Slice around the position: everything before it, plus everything after it:
text = "Hello World"
i = 5 # the space
# take everything before the index, then everything after it
result = text[:i] + text[i + 1:]
print("original:", repr(text))
print("index :", i, "which is", repr(text[i]))
print("result :", repr(result))
Output:
original: 'Hello World'
index : 5 which is ' '
result : 'HelloWorld'
text[:5] is 'Hello' and text[6:] is 'World'.The + 1 is what skips the unwanted character. Leave it out and you get the original string back.
Remember that indexes start at zero, so text[:0] + text[1:] removes the first character.
Why does del on a Python string raise a TypeError?
Python strings are immutable, so the two things you would try first both fail:
text = "Hello"
# neither of these works, because strings cannot be modified
try:
del text[0]
except TypeError as err:
print("del text[0] ->", type(err).__name__ + ":", err)
try:
text[0] = "J"
except TypeError as err:
print("text[0] = 'J' ->", type(err).__name__ + ":", err)
print()
print("every removal below builds a NEW string, so assign the result:")
text = text[1:]
print("text is now:", repr(text))
Output:
del text[0] -> TypeError: 'str' object doesn't support item deletion
text[0] = 'J' -> TypeError: 'str' object does not support item assignment
every removal below builds a NEW string, so assign the result:
text is now: 'ello'
doesn't support item deletion and does not support item assignment.| You tried | Error | Use instead |
|---|---|---|
del text[0] | doesn't support item deletion | text[1:] |
text[0] = "J" | does not support item assignment | "J" + text[1:] |
text.pop(0) | AttributeError | Convert to a list first |
The consequence is that you must assign the result. text[1:] on its own computes a new string and throws it away. It’s the same rule that applies when you reverse a string.
Why an out-of-range index removes nothing
Slicing clamps to the string’s length rather than raising, so a bad index fails quietly:
text = "Hello"
def remove_at(s, i):
return s[:i] + s[i + 1:]
print("index 1 :", repr(remove_at(text, 1)))
print("index 99 :", repr(remove_at(text, 99)), " <- unchanged, and no error")
print()
# slicing clamps, so nothing warns you that the index was wrong
print("a real check first:")
i = 99
if 0 <= i < len(text):
print(" removed:", repr(remove_at(text, i)))
else:
print(f" index {i} is outside 0..{len(text) - 1}")
Output:
index 1 : 'Hllo'
index 99 : 'Hello' <- unchanged, and no error
a real check first:
index 99 is outside 0..4
That silence is the problem. A loop with an off-by-one bug produces a string that looks fine and is missing nothing.
If the index comes from a calculation or user input, check it against len(text) before you slice.
Removing a character by value with replace
When you know the character rather than its position, replace is the tool:
text = "Hello World"
print("original :", repr(text))
print("first 'l' only:", repr(text.replace("l", "", 1)))
print("every 'l' :", repr(text.replace("l", "")))
print("the word :", repr(text.replace("World", "")))
print()
# several different characters in one pass
table = str.maketrans("", "", "lo")
print("remove l and o:", repr(text.translate(table)))
Output:
original : 'Hello World'
first 'l' only: 'Helo World'
every 'l' : 'Heo Word'
the word : 'Hello '
remove l and o: 'He Wrd'
replace for one character, translate for several.The third argument is a count. replace("l", "", 1) removes only the first match, which is what you want for stripping a single leading symbol.
str.translate with maketrans deletes several different characters in one pass. It is the fastest option when you have a list of characters to strip.
Removing characters with a regular expression
For patterns rather than fixed characters, re.sub replaces anything that matches:
import re
text = "Hello, World! 123"
print("original :", repr(text))
print("digits gone :", repr(re.sub(r"\d", "", text)))
print("punctuation gone:", repr(re.sub(r"[^\w\s]", "", text)))
print("letters only :", repr(re.sub(r"[^a-zA-Z]", "", text)))
print()
# keeping what you want is often clearer than removing what you do not
print("comprehension :", repr("".join(ch for ch in text if ch.isalpha())))
Output:
original : 'Hello, World! 123'
digits gone : 'Hello, World! '
punctuation gone: 'Hello World 123'
letters only : 'HelloWorld'
comprehension : 'HelloWorld'
re.sub(r"\d", "", text)— removes every digit.re.sub(r"[^\w\s]", "", text)— removes punctuation, keeps letters, digits and spaces.re.sub(r"[^a-zA-Z]", "", text)— keeps letters only.- A comprehension with
isalpha()does the same thing without importingre.
Describing what to keep is usually clearer than listing everything to remove. The same applies when you remove special characters.
Removing a range of characters from a string
The slice approach extends naturally to more than one character:
text = "Python Programming"
# a single index
i = 6
print("remove one :", repr(text[:i] + text[i + 1:]))
# a range of indexes
start, end = 6, 10
print("remove range:", repr(text[:start] + text[end:]))
# several scattered positions, removed at once
drop = {0, 6, 12}
print("remove set :", repr("".join(ch for n, ch in enumerate(text) if n not in drop)))
print()
# via a list, when you find that easier to read
chars = list(text)
chars.pop(6)
print("list.pop :", repr("".join(chars)))
Output:
remove one : 'PythonProgramming'
remove range: 'Pythongramming'
remove set : 'ythonProgrmming'
list.pop : 'PythonProgramming'
Removing a range is text[:start] + text[end:], where end is excluded just as it is in any slice.
For scattered positions, enumerate with a set of indexes to drop is the clearest way. Deleting them one at a time shifts every later index, which is a classic source of bugs.
A list is the other option. list(text), then pop, then "".join() gives you mutability when the logic is easier to write that way.
Which character removal method is fastest in Python?
On a 20,000-character string the difference is large:
import timeit
text = "abcdefghij" * 2000 # 20,000 characters
slice_way = timeit.timeit(lambda: text[:5000] + text[5001:], number=20_000)
list_way = timeit.timeit(lambda: "".join(ch for ch in text if ch != "a"), number=200)
print(f"slice removal, 20,000 runs : {slice_way * 1000:>7.0f} ms")
print(f"comprehension, 200 runs : {list_way * 1000:>7.0f} ms")
print()
print("the slice copies two blocks of memory and stops")
print("the comprehension tests every single character")
Output:
slice removal, 20,000 runs : 17 ms
comprehension, 200 runs : 122 ms
the slice copies two blocks of memory and stops
the comprehension tests every single character
The slice copies two blocks of memory and stops. The comprehension inspects every character and reassembles the string one piece at a time.
For a single known position, always slice. Save the comprehension for when you genuinely need to test each character.
Common character removal mistakes
| Symptom | Cause | Fix |
|---|---|---|
TypeError on del | Strings are immutable | Slice around the index |
| Nothing changed | Result not assigned | text = text[:i] + text[i+1:] |
| Wrong character removed | Off-by-one on the index | The slice needs i + 1 |
| Too many removed | replace with no count | Pass 1 as the third argument |
| Silent no-op | Index beyond the string | Check against len(text) |
Other Python string editing guides:
- Remove the last character from a string
- Remove newlines from a string
- Get the first n characters
- Remove special characters
- Remove Unicode characters
- Reverse a string in Python
Frequently asked questions
How do I remove a character from a string in Python?
Slice around it with text[:i] + text[i+1:] for a position, or text.replace(ch, "") for a character. String methods are listed in the Python string methods reference.
Why can’t I use del on a string character?
Strings are immutable, so del text[0] raises TypeError: 'str' object doesn't support item deletion. Build a new string instead.
How do I remove a character at a specific index?
text[:i] + text[i+1:]. The + 1 is what skips the character at position i.
How do I remove only the first occurrence of a character?
Pass a count: text.replace("x", "", 1). Without it, every occurrence is removed.
How do I remove several different characters at once?
text.translate(str.maketrans("", "", "abc")) removes a, b and c in a single pass.
Why does removing at an out-of-range index do nothing?
Slicing clamps to the string length instead of raising. Check the index against len(text) first.
What is the fastest way to remove a character?
Slicing, when you know the position. It copies two blocks of memory rather than testing every character.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn