Toolmingo
Guides8 min read

Python String Methods: Complete Reference with Examples

Master all Python string methods — searching, slicing, splitting, replacing, formatting, case conversion, and stripping with practical code examples.

Python strings are immutable sequences of Unicode characters. Every string method returns a new string — it never modifies the original. This guide covers every built-in string method with examples, including slicing, formatting, and the most common real-world patterns.


Quick Reference

Method What it does
s.upper() / s.lower() Convert case
s.title() / s.capitalize() Capitalise words / first char
s.strip() / s.lstrip() / s.rstrip() Remove whitespace (or chars)
s.split(sep) Split into list
s.rsplit(sep, maxsplit) Split from right
s.splitlines() Split on line endings
sep.join(iterable) Join list into string
s.replace(old, new) Replace substrings
s.find(sub) / s.rfind(sub) Index of first/last match (-1 if not found)
s.index(sub) / s.rindex(sub) Like find but raises ValueError
s.count(sub) Count non-overlapping occurrences
s.startswith(prefix) Starts with prefix?
s.endswith(suffix) Ends with suffix?
s.in (sub in s) Contains substring?
s.format(**kwargs) Format string
f"..." f-string (preferred)
s.zfill(width) Pad with zeros on left
s.ljust(w) / s.rjust(w) / s.center(w) Pad with spaces
s.encode(encoding) Encode to bytes
b.decode(encoding) Decode bytes to string
s.isdigit() / s.isalpha() / s.isalnum() Character class checks
s.isspace() / s.isupper() / s.islower() More checks
s.translate(table) Character-by-character replace
s.maketrans(x, y) Build translation table

Creating Strings

# Single, double, triple quotes
name = 'Ana'
greeting = "Hello, world!"
poem = """Line one
Line two
Line three"""

# Raw string — backslashes not interpreted
path = r"C:\Users\ana\docs"
regex = r"\d+\.\d+"

# Byte string
data = b"binary content"

# f-string (Python 3.6+)
age = 30
msg = f"Ana is {age} years old"           # "Ana is 30 years old"
msg = f"Pi is {3.14159:.2f}"              # "Pi is 3.14"
msg = f"Hex: {255:#x}"                    # "Hex: 0xff"
msg = f"{name!r}"                         # "'Ana'"  (repr)
msg = f"{name!s}"                         # "Ana"    (str)
msg = f"{name!a}"                         # "'Ana'"  (ascii)

# Python 3.12+ — nested quotes inside f-strings
label = f"Result: {', '.join(['a', 'b', 'c'])}"

Slicing

s = "Hello, World!"

s[0]       # "H"
s[-1]      # "!"
s[7:]      # "World!"
s[:5]      # "Hello"
s[7:12]    # "World"
s[::2]     # "Hlo ol!"  (every 2nd char)
s[::-1]    # "!dlroW ,olleH"  (reverse)

# Safe slice — never raises IndexError
s[100:]    # ""   (not an error)

Case Conversion

s = "hello, WORLD!"

s.upper()        # "HELLO, WORLD!"
s.lower()        # "hello, world!"
s.title()        # "Hello, World!"
s.capitalize()   # "Hello, world!"  (only first char up, rest down)
s.swapcase()     # "HELLO, world!"

# Comparison ignoring case
"Python".casefold() == "python"   # True
"Straße".casefold()               # "strasse"  (German ß → ss)
"Python".lower() == "python"      # True  (works for ASCII, prefer casefold for Unicode)

Searching and Finding

s = "the cat sat on the mat"

# find returns index, -1 if not found
s.find("cat")          # 4
s.find("dog")          # -1
s.find("at", 5)        # 8   (search from index 5)
s.rfind("at")          # 19  (last occurrence)

# index raises ValueError if not found
s.index("cat")         # 4
# s.index("dog")       # ValueError!

# contains
"cat" in s             # True
"dog" in s             # False

# count
s.count("at")          # 3
s.count("the")         # 2

# startswith / endswith (accept tuple of prefixes)
"readme.md".endswith((".md", ".txt"))    # True
"image.png".startswith(("img", "image")) # True

Replacing

s = "banana"

s.replace("a", "o")        # "bonono"
s.replace("a", "o", 1)     # "bonana"  (max 1 replacement)
s.replace("an", "")        # "bna"

# Remove a character
"hello world".replace(" ", "")  # "helloworld"

# Chain replacements
text = "Hello\r\nWorld\r\n"
text.replace("\r\n", "\n")       # "Hello\nWorld\n"

# translate for multiple single-char replacements (faster than chaining replace)
table = str.maketrans("aeiou", "AEIOU")
"hello world".translate(table)   # "hEllO wOrld"

# Delete specific characters with translate
delete_table = str.maketrans("", "", "aeiou")
"hello world".translate(delete_table)   # "hll wrld"

Splitting and Joining

# split — default splits on any whitespace, removes empty strings
"  hello   world  ".split()         # ["hello", "world"]
"a,b,,c".split(",")                 # ["a", "b", "", "c"]
"a,b,c".split(",", maxsplit=1)      # ["a", "b,c"]

# rsplit — split from right
"path/to/file.txt".rsplit("/", 1)   # ["path/to", "file.txt"]

# splitlines — handles \n, \r\n, \r
"line1\nline2\r\nline3".splitlines()   # ["line1", "line2", "line3"]

# partition — returns (before, sep, after), always 3 parts
"host:port".partition(":")   # ("host", ":", "port")
"no sep here".partition(":")  # ("no sep here", "", "")

# join — join iterable with separator
", ".join(["a", "b", "c"])    # "a, b, c"
"".join(["h", "e", "y"])      # "hey"
"\n".join(["line1", "line2"]) # "line1\nline2"

# join is much faster than concatenation in a loop
# WRONG (slow): result = ""; for word in words: result += word + " "
# RIGHT (fast): result = " ".join(words)

Stripping Whitespace

s = "  hello world  "

s.strip()    # "hello world"   (both ends)
s.lstrip()   # "hello world  " (left only)
s.rstrip()   # "  hello world" (right only)

# Strip specific characters (any combination, not a substring)
"---TITLE---".strip("-")     # "TITLE"
"xxABCxx".strip("x")        # "ABC"
"/path/to/dir/".strip("/")  # "path/to/dir"

# Python 3.9+ — remove prefix/suffix exactly (not char-by-char)
"Hello, World!".removeprefix("Hello, ")   # "World!"
"Hello, World!".removesuffix("!")         # "Hello, World"

# removeprefix/removesuffix return original if no match (no error)
"World".removeprefix("Hello, ")           # "World"

Padding and Alignment

# zfill — pad with zeros (useful for codes, IDs)
"42".zfill(5)       # "00042"
"-42".zfill(5)      # "-0042"  (sign preserved)

# ljust / rjust / center (default fill char is space)
"hi".ljust(10)          # "hi        "
"hi".rjust(10)          # "        hi"
"hi".center(10)         # "    hi    "
"hi".center(10, "-")    # "----hi----"

# f-string equivalent (preferred)
f"{'hi':<10}"   # "hi        "  (left align)
f"{'hi':>10}"   # "        hi"  (right align)
f"{'hi':^10}"   # "    hi    "  (center)
f"{'hi':-^10}"  # "----hi----"  (fill char -)
f"{42:05d}"     # "00042"       (zero-pad integer)

String Formatting

# f-strings (modern, Python 3.6+)
name, price = "Widget", 9.99
f"{name} costs ${price:.2f}"          # "Widget costs $9.99"
f"{1_000_000:,}"                       # "1,000,000"
f"{0.75:.1%}"                          # "75.0%"
f"{255:08b}"                           # "11111111"  (binary)
f"{255:#010x}"                         # "0x000000ff"

# str.format() (older style, still widely used)
"{} costs ${:.2f}".format(name, price)
"{name} costs ${price:.2f}".format(name=name, price=price)

# % formatting (legacy, avoid in new code)
"%s costs $%.2f" % (name, price)

# Template strings (safe for user-controlled strings)
from string import Template
t = Template("$name costs $$price")
t.substitute(name="Widget", price=9.99)   # "Widget costs $9.99"

Checking String Content

# Character class predicates
"123".isdigit()        # True
"abc".isalpha()        # True
"abc123".isalnum()     # True
"   ".isspace()        # True
"HELLO".isupper()      # True
"hello".islower()      # True
"Hello World".istitle() # True

# isdigit vs isnumeric vs isdecimal (subtle differences)
"²".isdigit()          # True  (superscript 2)
"²".isnumeric()        # True
"²".isdecimal()        # False  (not a decimal digit 0-9)
"½".isnumeric()        # True   (fraction)
"½".isdigit()          # False

# For ASCII digit check use:
"123".isdecimal()      # True  — safest for "is this a plain number?"

# Check if valid Python identifier
"my_var".isidentifier()    # True
"2var".isidentifier()      # False
"class".isidentifier()     # True  (but it's a keyword — check separately)

import keyword
keyword.iskeyword("class")  # True

Encoding and Bytes

s = "Hello, 世界"

# Encode string → bytes
b = s.encode("utf-8")     # b'Hello, \xe4\xb8\x96\xe7\x95\x8c'
b = s.encode("utf-16")
b = s.encode("ascii", errors="ignore")    # b'Hello, '
b = s.encode("ascii", errors="replace")  # b'Hello, ??'
b = s.encode("ascii", errors="xmlcharrefreplace")  # b'Hello, &#19990;&#30028;'

# Decode bytes → string
b.decode("utf-8")
b.decode("utf-8", errors="replace")   # replace undecodable bytes with ?

# Check encoding
import chardet  # pip install chardet
chardet.detect(b)  # {"encoding": "utf-8", "confidence": 0.99}

Real-World Patterns

Parse a CSV line

line = "Ana,30,Podgorica"
name, age, city = line.split(",")
# name="Ana", age="30", city="Podgorica"

# Handle quoted fields with csv module instead
import csv
row = next(csv.reader(['Ana,"City, Town",30']))
# ["Ana", "City, Town", "30"]

Clean user input

def clean(text: str) -> str:
    return text.strip().lower().replace("\r\n", "\n")

raw = "  Hello World  \r\n"
clean(raw)  # "hello world  \n"

Build a slug

import re

def slugify(text: str) -> str:
    text = text.lower().strip()
    text = re.sub(r"[^\w\s-]", "", text)
    text = re.sub(r"[\s_-]+", "-", text)
    text = text.strip("-")
    return text

slugify("Hello, World! 2024")  # "hello-world-2024"

Extract domain from URL

url = "https://www.example.com/path?q=1"
domain = url.split("//")[-1].split("/")[0]   # "www.example.com"

# Or with urllib
from urllib.parse import urlparse
urlparse(url).netloc   # "www.example.com"

Truncate text with ellipsis

def truncate(text: str, max_len: int = 100) -> str:
    if len(text) <= max_len:
        return text
    return text[:max_len - 3].rstrip() + "..."

truncate("A very long piece of text here", 20)  # "A very long piece..."

Count words

text = "  Hello world  how are  you  "
word_count = len(text.split())   # 5  (split() handles multiple spaces)

Wrap long text

import textwrap

text = "This is a very long line that needs to be wrapped at a reasonable column width."
print(textwrap.fill(text, width=40))
# This is a very long line that needs
# to be wrapped at a reasonable column
# width.

textwrap.dedent("""
    Hello
    World
""").strip()   # "Hello\nWorld"

Common Mistakes

Mistake Problem Fix
s[0] = "H" Strings are immutable — raises TypeError s = "H" + s[1:]
"".join(x) on non-strings TypeError: sequence item must be str "".join(str(x) for x in items)
s.split() vs s.split(" ") split() collapses whitespace; split(" ") keeps empty strings Use split() for general whitespace
s.find() vs s.index() find returns -1; index raises ValueError Use find when absence is normal
"ab" * 3 confusion "ababab" — not "aabbbb" Use "".join(c * 3 for c in "ab") if needed
s.upper() == other without normalising Unicode case comparison fails Use s.casefold() for robust case-insensitive compare
+ concatenation in loop O(n²) — creates new string each iteration Use "".join(parts) or io.StringIO

FAQ

How do I check if a string contains a substring?
Use in: "world" in "hello world"True. Use .find() when you also need the position.

What's the difference between str.split() and re.split()?
str.split(sep) uses a literal separator; re.split(pattern, s) uses a regular expression. For complex delimiters (multiple chars, patterns) use re.split.

How do I reverse a string?
s[::-1]. Slicing with step -1 returns a reversed copy.

How do I remove all whitespace from a string?
"".join(s.split()) removes all whitespace including internal spaces. s.strip() only removes leading/trailing.

How do I convert a string to a list of characters?
list("hello")["h", "e", "l", "l", "o"]. Or [*"hello"] with unpacking.

How do I check if a string is a number?
s.isdecimal() for plain integers. For floats: try: float(s) except ValueError: .... Avoid isdigit() for this — it accepts superscripts like ².

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools