Python Strings: Complete Guide with Examples (2026)
Strings are one of the most widely used data types in Python. Every time you print a message, read a file, take user input, build a URL, or parse JSON, strings are working. In this guide you’ll learn all about Python strings, from the basics to formatting, methods, Unicode and best practices, with lots of examples you can run yourself.
- What is a string?
- Creating strings
- Escape characters and raw strings
- Strings are immutable
- Indexing and slicing
- Basic operations
- Important string methods
- String formatting
- Unicode, encoding and bytes
- Comparing strings
- A quick look at regular expressions
- Performance tips
- Common mistakes
- Practice problems
- Summary
1. What is a String in Python?
A string is an ordered sequence of Unicode characters. In Python 3 the type is called str. Strings are written inside quotes, and they are immutable, which means you cannot change them after they are created.
name = "Python"
print(type(name)) # <class 'str'>
print(len(name)) # 62. Creating Strings
Single, double and triple quotes
a = 'Hello'
b = "World"
c = """This is a
multi-line string"""
d = '''Triple single quotes
work the same way'''
print(a, b)
print(c)Single and double quotes are identical. Use double quotes when the text contains an apostrophe, and single quotes when it contains double quotes:
print("It's a nice day")
print('He said "Hello"')Empty strings and the str() constructor
empty = ""
print(len(empty)) # 0
print(bool(empty)) # False (empty strings are falsy)
print(str(123)) # '123'
print(str(3.14)) # '3.14'
print(str([1, 2, 3])) # '[1, 2, 3]'Taking input
name = input("Enter your name: ") # input() always returns a string
print("Hello,", name)3. Escape Characters and Raw Strings
A backslash \ lets you insert special characters.
| Escape | Meaning |
|---|---|
\n | New line |
\t | Tab |
\\ | Backslash |
\' | Single quote |
\" | Double quote |
\r | Carriage return |
\uXXXX | Unicode character (16-bit) |
print("Line 1\nLine 2")
print("Name:\tAlice")
print("She said \"Hi\"")
print("C:\\Users\\Alice")
print("\u2764") # a heart symbolRaw strings
Prefix a string with r and backslashes are treated literally. This is very useful for file paths and regular expressions.
path = r"C:\new_folder\test"
print(path) # C:\new_folder\test4. Strings are Immutable
You cannot modify a string in place. Trying to do so raises an error:
s = "hello"
s[0] = "H" # TypeError: 'str' object does not support item assignmentInstead, create a new string:
s = "hello"
s = "H" + s[1:]
print(s) # HelloBecause strings are immutable, they can be used as dictionary keys and set elements.
5. Indexing and Slicing
Indexing
Each character has a position (index). Counting starts at 0 from the left, and at -1 from the right.
s = "PYTHON"
# P Y T H O N
# 0 1 2 3 4 5
# -6 -5 -4 -3 -2 -1
print(s[0]) # P
print(s[3]) # H
print(s[-1]) # N
print(s[-3]) # H
print(s[10]) # IndexError: string index out of rangeSlicing
The syntax is string[start:stop:step]. The stop index is not included.
s = "PYTHON"
print(s[0:3]) # PYT
print(s[:3]) # PYT
print(s[3:]) # HON
print(s[1:5]) # YTHO
print(s[::2]) # PTO (every 2nd character)
print(s[::-1]) # NOHTYP (reversed)
print(s[-3:]) # HON
print(s[:-1]) # PYTHO
print(s[2:100]) # THON (slices never raise IndexError)6. Basic Operations
Concatenation and repetition
first = "Hello"
second = "World"
print(first + " " + second) # Hello World
print("ab" * 3) # ababab
print("-" * 20) # --------------------
# You cannot add a string and a number directly:
# print("Age: " + 25) # TypeError
print("Age: " + str(25)) # Age: 25Length and membership
s = "Python programming"
print(len(s)) # 18
print("Python" in s) # True
print("Java" in s) # False
print("Java" not in s) # TrueLooping through a string
for ch in "abc":
print(ch)
for i, ch in enumerate("abc"):
print(i, ch)7. Important String Methods
Every string method returns a new string; the original never changes.
Case methods
s = "hello World"
print(s.upper()) # HELLO WORLD
print(s.lower()) # hello world
print(s.title()) # Hello World
print(s.capitalize()) # Hello world
print(s.swapcase()) # HELLO wORLD
print("Straße".casefold()) # strasse (best for case-insensitive comparison)Searching
s = "banana"
print(s.find("an")) # 1
print(s.find("xyz")) # -1 (not found)
print(s.index("an")) # 1
# s.index("xyz") # ValueError
print(s.rfind("an")) # 3 (search from the right)
print(s.count("a")) # 3
print(s.startswith("ban")) # True
print(s.endswith("na")) # TrueTip: find() returns -1 when nothing is found, while index() raises a ValueError.
Removing whitespace
s = " hello "
print(repr(s.strip())) # 'hello'
print(repr(s.lstrip())) # 'hello '
print(repr(s.rstrip())) # ' hello'
print("xxhixx".strip("x")) # hiReplacing
s = "I like cats. Cats are great."
print(s.replace("Cats", "dogs")) # I like cats. dogs are great.
print("aaaa".replace("a", "b", 2)) # bbaa (only first 2)split() and join()
text = "apple,banana,cherry"
fruits = text.split(",")
print(fruits) # ['apple', 'banana', 'cherry']
print("a b c".split()) # ['a', 'b', 'c'] (splits on any whitespace)
print("a-b-c-d".split("-", 2)) # ['a', 'b', 'c-d']
print(" | ".join(fruits)) # apple | banana | cherry
print("".join(["a", "b", "c"])) # abc
lines = "one\ntwo\nthree".splitlines()
print(lines) # ['one', 'two', 'three']
print("key=value=x".partition("=")) # ('key', '=', 'value=x')Checking content
| Method | Returns True if... | Example |
|---|---|---|
isalpha() | all characters are letters | "abc".isalpha() → True |
isdigit() | all characters are digits | "123".isdigit() → True |
isalnum() | letters or digits only | "abc123".isalnum() → True |
isspace() | only whitespace | " ".isspace() → True |
isupper() | all cased letters are uppercase | "ABC".isupper() → True |
islower() | all cased letters are lowercase | "abc".islower() → True |
istitle() | title-cased | "Hello World".istitle() → True |
Note that all of these return False for an empty string.
Alignment and padding
print("hi".center(10, "*")) # ****hi****
print("hi".ljust(6, ".")) # hi....
print("hi".rjust(6, ".")) # ....hi
print("42".zfill(5)) # 00042Other useful methods
print("a\tb".expandtabs(4)) # a b
print("hello".removeprefix("he")) # llo (Python 3.9+)
print("hello.py".removesuffix(".py")) # hello (Python 3.9+)
table = str.maketrans("abc", "123")
print("aabbcc".translate(table)) # 1122338. String Formatting
Python offers three ways to put values inside strings. The modern and recommended way is f-strings.
a) f-strings (Python 3.6+)
name = "Alice"
age = 30
print(f"My name is {name} and I am {age} years old.")
print(f"Next year I will be {age + 1}.")
print(f"{name.upper()} has {len(name)} letters.")
# Debugging shortcut (3.8+)
x = 10
print(f"{x = }") # x = 10Format specifiers
pi = 3.14159265
print(f"{pi:.2f}") # 3.14
print(f"{1234567:,}") # 1,234,567
print(f"{0.256:.1%}") # 25.6%
print(f"{42:05d}") # 00042
print(f"{255:b}") # 11111111 (binary)
print(f"{255:x}") # ff (hex)
print(f"{255:#o}") # 0o377 (octal)
print(f"{1500000:e}") # 1.500000e+06
# Width and alignment
print(f"[{'left':<10}]") # [left ]
print(f"[{'right':>10}]") # [ right]
print(f"[{'mid':^10}]") # [ mid ]
print(f"[{'pad':*^11}]") # [****pad****]b) The format() method
print("Hello, {}!".format("Bob"))
print("{0} {1} {0}".format("a", "b")) # a b a
print("{name} is {age}".format(name="Eve", age=25))
print("{:.3f}".format(2.71828)) # 2.718c) The % operator (old style)
print("Hello, %s! You are %d years old." % ("Sam", 22))
print("Pi is about %.2f" % 3.14159)You will still see this in older code, but prefer f-strings in new code.
Template strings
from string import Template
t = Template("Hello, $name!")
print(t.substitute(name="World"))Template strings are handy when the format string comes from users, because they are safer than format() with untrusted input.
9. Unicode, Encoding and Bytes
Python 3 strings are Unicode, so they can hold text from any language and emojis.
s = "नमस्ते 😀"
print(len(s)) # 8
print(ord("A")) # 65
print(chr(65)) # A
print(chr(0x1F600)) # 😀Encoding and decoding
str is text; bytes is raw data. Convert between them with encode() and decode().
text = "café"
data = text.encode("utf-8")
print(data) # b'caf\xc3\xa9'
print(len(text), len(data)) # 4 5
print(data.decode("utf-8")) # café
# Handling errors
print("café".encode("ascii", errors="ignore")) # b'caf'
print("café".encode("ascii", errors="replace")) # b'caf?'Always specify encoding="utf-8" when reading or writing text files:
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("Hello, world")10. Comparing Strings
print("apple" == "apple") # True
print("apple" == "Apple") # False (case-sensitive)
print("apple" < "banana") # True (compared by Unicode code points)
print("a" < "B") # False ('a' = 97, 'B' = 66)
# Case-insensitive comparison
print("Python".casefold() == "PYTHON".casefold()) # True== vs is
== compares values. is checks whether two names point to the same object. Always use == to compare strings.
a = "hello world"
b = "".join(["hello", " world"])
print(a == b) # True
print(a is b) # usually False; do not rely on thisSorting strings
words = ["banana", "Apple", "cherry"]
print(sorted(words)) # ['Apple', 'banana', 'cherry']
print(sorted(words, key=str.lower)) # ['Apple', 'banana', 'cherry']
print(sorted(words, key=len)) # ['Apple', 'banana', 'cherry']11. A Quick Look at Regular Expressions
For complex pattern matching, use the built-in re module.
import re
text = "Contact: alice@example.com, bob@test.org"
emails = re.findall(r"[\w.]+@[\w.]+\.\w+", text)
print(emails) # ['alice@example.com', 'bob@test.org']
print(re.sub(r"\d+", "#", "Room 101, Floor 4")) # Room #, Floor #
m = re.search(r"(\d{3})-(\d{4})", "Call 555-1234")
if m:
print(m.group(1), m.group(2)) # 555 123412. Performance Tips
- Use
join()to build large strings. Repeated+=in a loop can be slow because a new string is created each time.
# Slow for large loops
result = ""
for i in range(1000):
result += str(i)
# Better
result = "".join(str(i) for i in range(1000))- Use
infor simple membership checks instead offind(). - Prefer f-strings, they are the fastest formatting option.
- Use
io.StringIOif you need a mutable, file-like text buffer.
13. Common Mistakes
- Expecting methods to change the string.
Python
s = "hello" s.upper() # result is thrown away print(s) # hello s = s.upper() # correct print(s) # HELLO - Mixing strings and numbers.
"5" + 5raises aTypeError; useint("5") + 5or"5" + str(5). - Forgetting that
input()returns a string. Convert withint()orfloat(). - Using
isinstead of==for comparing text. - Off-by-one slicing errors. Remember that the stop index is excluded.
- Backslashes in Windows paths. Use raw strings or forward slashes.
14. Practice Problems
Problem 1: Check for a palindrome
def is_palindrome(s):
cleaned = "".join(ch.lower() for ch in s if ch.isalnum())
return cleaned == cleaned[::-1]
print(is_palindrome("A man, a plan, a canal: Panama")) # True
print(is_palindrome("Hello")) # FalseProblem 2: Count vowels
def count_vowels(s):
return sum(1 for ch in s.lower() if ch in "aeiou")
print(count_vowels("Python Programming")) # 4Problem 3: Word frequency
from collections import Counter
text = "the cat and the hat and the bat"
freq = Counter(text.split())
print(freq) # Counter({'the': 3, 'and': 2, 'cat': 1, 'hat': 1, 'bat': 1})
print(freq.most_common(1)) # [('the', 3)]Problem 4: Check for an anagram
def is_anagram(a, b):
return sorted(a.lower()) == sorted(b.lower())
print(is_anagram("Listen", "Silent")) # TrueProblem 5: Reverse each word
s = "hello world"
print(" ".join(w[::-1] for w in s.split())) # olleh dlrowProblem 6: Caesar cipher
def caesar(text, shift):
result = []
for ch in text:
if ch.isalpha():
base = ord("A") if ch.isupper() else ord("a")
result.append(chr((ord(ch) - base + shift) % 26 + base))
else:
result.append(ch)
return "".join(result)
print(caesar("Hello, World!", 3)) # Khoor, Zruog!15. Summary and Cheat Sheet
| Task | Use |
|---|---|
| Length | len(s) |
| Slice / reverse | s[a:b], s[::-1] |
| Change case | upper(), lower(), title() |
| Search | find(), index(), count(), in |
| Clean | strip(), replace() |
| Split / combine | split(), join() |
| Validate | isdigit(), isalpha(), isalnum() |
| Format | f-strings: f"{value:.2f}" |
| Bytes | encode(), decode() |
Key points to remember:
- Strings are immutable sequences of Unicode characters.
- Indexing starts at 0; negative indexes count from the end.
- String methods return new strings; assign the result to keep it.
- Use f-strings for formatting and
join()for building large strings. - Use raw strings for regex patterns and Windows paths.
- Always specify UTF-8 encoding when working with files.
That covers everything you need to work confidently with strings in Python. Try the practice problems, experiment in the Python shell, and you will master strings quickly. If you found this guide useful, share it and leave a comment with your questions!
Frequently Asked Questions (FAQ)
What is a string in Python?
A string is an immutable sequence of Unicode characters, represented by the str type and written inside single, double, or triple quotes.
Are strings mutable in Python?
No. Strings are immutable. Methods like upper() or replace() return a new string instead of changing the original.
How do I reverse a string in Python?
Use slicing: s[::-1].
What is the best way to format strings in Python?
f-strings (Python 3.6+), for example f"Hello, {name}". They are readable and fast.
How do I check if a string contains a substring?
Use the in operator: "cat" in "concatenate" returns True.
What is the difference between find() and index()?
find() returns -1 when the substring is missing, while index() raises a ValueError.
How do I convert a string to an integer?
Use int("42"). Wrap it in try/except ValueError if the input may not be numeric.
Next up: Python Lists, Tuples and Dictionaries.