Modify Strings
Learn how to modify strings in Python using concatenation, slicing, case methods, replace, strip, split, join, and more. Includes runnable examples.
Python strings are sequences of characters enclosed in quotes. Although strings are immutable — you cannot change them in place — Python gives you a rich set of operators and methods that return new, modified strings. This chapter covers the most important techniques: concatenation, repetition, case conversion, slicing, replacing substrings, stripping whitespace, splitting and joining, and more.
Key Concept: Strings Are Immutable
Before diving in, it is important to understand that every "modification" method returns a new string. The original string is never changed.
greeting = "hello"
upper_greeting = greeting.upper()
print(greeting) # hello (unchanged)
print(upper_greeting) # HELLO (new string)This means you must assign the result to a variable (or use it directly) to keep the change.
String Concatenation
Concatenation combines two or more strings into one using the + operator. You can chain as many strings as you need.
Concatenate strings in Python
Concatenating with Variables and Literals
You can mix string variables with string literals:
first_name = "Ada"
last_name = "Lovelace"
full_name = first_name + " " + last_name
print(full_name) # Ada LovelaceFor larger amounts of text, consider format strings or f-strings which are easier to read than long chains of +.
String Repetition
The * operator repeats a string a given number of times. This is useful for generating separators, padding, or simple patterns.
Repeat a string in Python
Changing Case
Python provides several methods to change the capitalisation of a string.
| Method | What it does | Example input → output |
|---|---|---|
upper() | All letters uppercase | "hello" → "HELLO" |
lower() | All letters lowercase | "HELLO" → "hello" |
title() | First letter of each word capitalised | "hello world" → "Hello World" |
capitalize() | First letter capitalised, rest lowercase | "hELLO" → "Hello" |
swapcase() | Swaps upper↔lower for every letter | "Hello" → "hELLO" |
Convert a string to uppercase or lowercase in Python
Case methods are commonly used when comparing user input regardless of how it was typed:
answer = input("Type yes or no: ")
if answer.lower() == "yes":
print("You said yes!")Slicing Strings
Slicing extracts part of a string using the [start:stop:step] syntax. The result is a new string containing the characters from index start up to but not including index stop.
H e l l o , W o r l d !
0 1 2 3 4 5 6 7 8 9 10 11 12
-13-12-11-10-9 -8 -7 -6 -5 -4 -3 -2 -1Slice strings in Python
When to Use Negative Indices
Negative indices count from the end of the string. Index -1 is the last character, -2 is the second-to-last, and so on. This is handy when you want the tail of a string without knowing its length:
filename = "report_2024.csv"
extension = filename[-3:]
print(extension) # csvFor a dedicated deep-dive, see the Slicing Strings chapter.
Replacing Substrings
The replace(old, new) method returns a copy of the string with every occurrence of old replaced by new. Pass a third argument count to limit how many replacements are made.
Replace a part of a string in Python
text = "I like cats. Cats are great. Cats!"
print(text.replace("Cats", "Dogs")) # replaces all occurrences
print(text.replace("Cats", "Dogs", 1)) # replaces first occurrence onlyI like cats. Dogs are great. Dogs!
I like cats. Dogs are great. Cats!Note that replace() is case-sensitive: "cats" and "Cats" are treated as different substrings.
Stripping Whitespace
Whitespace characters (spaces, tabs, newlines) at the start or end of a string often need to be removed, especially when processing user input or reading files.
| Method | Removes whitespace from |
|---|---|
strip() | Both ends |
lstrip() | Left (start) only |
rstrip() | Right (end) only |
raw = " hello world "
print(repr(raw.strip())) # 'hello world'
print(repr(raw.lstrip())) # 'hello world '
print(repr(raw.rstrip())) # ' hello world'You can also strip specific characters by passing them as an argument:
path = "///usr/local/bin///"
print(path.strip("/")) # usr/local/binSplitting Strings
The split(sep) method splits a string on a separator and returns a list of substrings. With no argument it splits on any whitespace and removes empty strings.
sentence = "Python is easy to learn"
words = sentence.split()
print(words) # ['Python', 'is', 'easy', 'to', 'learn']
csv_row = "Alice,30,Engineer"
fields = csv_row.split(",")
print(fields) # ['Alice', '30', 'Engineer']Pass a second argument maxsplit to limit the number of splits:
data = "one:two:three:four"
print(data.split(":", 2)) # ['one', 'two', 'three:four']Joining Strings
join() is the reverse of split(). It combines a list of strings into one, placing a separator between each element. The separator is the string on which you call join().
words = ["Python", "is", "fun"]
sentence = " ".join(words)
print(sentence) # Python is fun
path_parts = ["usr", "local", "bin"]
path = "/".join(path_parts)
print(path) # usr/local/binUsing join() is far more efficient than concatenating strings in a loop, because each + creates a new string object. join() allocates the final string only once.
Searching Within Strings
Several methods help you find text inside a string.
find() and index()
find(sub) returns the index of the first occurrence of sub, or -1 if not found. index(sub) does the same but raises ValueError instead of returning -1.
text = "the quick brown fox"
print(text.find("quick")) # 4
print(text.find("slow")) # -1
print(text.index("brown")) # 10startswith() and endswith()
These return True or False and are a cleaner alternative to slicing when you need to check the beginning or end of a string.
url = "https://www.w3docs.com"
print(url.startswith("https")) # True
print(url.endswith(".com")) # True
print(url.startswith("http://")) # FalseYou can pass a tuple of prefixes/suffixes to check for multiple options at once:
filename = "photo.jpg"
print(filename.endswith((".jpg", ".jpeg", ".png"))) # Truecount()
count(sub) returns how many times sub appears in the string (non-overlapping).
text = "banana"
print(text.count("a")) # 3
print(text.count("an")) # 2Checking String Properties
Python has a family of is* methods that return True or False about the content of a string.
print("hello".isalpha()) # True – all alphabetic
print("hello123".isalnum()) # True – all alphanumeric
print("12345".isdigit()) # True – all digits
print(" ".isspace()) # True – all whitespace
print("Hello World".istitle()) # True – title-caseThese are especially useful for input validation.
Practical Example: Cleaning User Input
Real-world string modification often combines several techniques:
raw_input = " Ada Lovelace "
# Clean and normalise
name = raw_input.strip() # remove surrounding spaces
name = name.title() # ensure proper capitalisation
parts = name.split() # split into first / last
first, last = parts[0], parts[1]
print(f"First: {first}, Last: {last}") # First: Ada, Last: LovelaceQuick Reference
| Operation | Syntax | Returns |
|---|---|---|
| Concatenate | a + b | New string |
| Repeat | s * n | New string |
| Uppercase | s.upper() | New string |
| Lowercase | s.lower() | New string |
| Title case | s.title() | New string |
| Slice | s[start:stop:step] | New string |
| Replace | s.replace(old, new) | New string |
| Strip | s.strip() | New string |
| Split | s.split(sep) | List |
| Join | sep.join(iterable) | New string |
| Find | s.find(sub) | Integer index or -1 |
| Count | s.count(sub) | Integer |
| Starts with | s.startswith(prefix) | Boolean |
| Ends with | s.endswith(suffix) | Boolean |
For the complete list of built-in string methods, see String Methods. To learn about escape sequences like \n and \t, see Escape Characters. For powerful text search and manipulation using patterns, see Python Regex.