str has ~47 methods. Knowing the right one — partition instead of a regex, casefold instead of lower, removeprefix instead of strip — makes text code shorter and correct.
Case conversion
| Method | Does | Example → result |
|---|---|---|
lower() / upper() | All lower / upper case | 'PyThon'.lower() → 'python' |
casefold() | Aggressive lower-casing for caseless comparison | 'Straße'.casefold() → 'strasse' |
title() | First letter of every word upper | 'hello world'.title() → 'Hello World' |
capitalize() | First character upper, rest lower | 'hELLO'.capitalize() → 'Hello' |
swapcase() | Invert each letter's case | 'Ab'.swapcase() → 'aB' |
print("Straße".lower(), "Straße".casefold()) # straße strasse
print("STRASSE".casefold() == "Straße".casefold()) # True
print("STRASSE".lower() == "Straße".lower()) # False
print("they're bill's".title()) # They'Re Bill'S
print(" ".join(w.capitalize() for w in "they're bill's".split())) # They're Bill'sSearching
| Method | Returns | If not found |
|---|---|---|
s.find(sub[, start[, end]]) | Lowest index | -1 |
s.rfind(sub) | Highest index | -1 |
s.index(sub) / s.rindex(sub) | Like find / rfind | raises ValueError |
s.count(sub) | Number of non-overlapping occurrences | 0 |
s.startswith(p) / s.endswith(p) | bool — p may be a tuple of options | False |
sub in s | bool — the most readable test | False |
path = "reports/2026/q1.final.csv"
print(path.find("/"), path.rfind("/"), path.find("zip")) # 7 12 -1
print(path[path.rfind(".") + 1:]) # csv
print(path.endswith((".csv", ".tsv"))) # True
print("aaaa".count("aa"), "2026" in path) # 2 True
print("banana".find("a", 2), "banana".find("a", 2, 3)) # 3 -1Splitting family
| Method | Behaviour |
|---|---|
s.split() | Split on runs of any whitespace, dropping empty strings and leading/trailing space |
s.split(sep) | Split on an exact separator — keeps empty strings between adjacent separators |
s.split(sep, maxsplit) | At most maxsplit splits, from the left |
s.rsplit(sep, maxsplit) | At most maxsplit splits, from the right |
s.splitlines() | Split on \n, \r\n, \r… without a trailing empty item |
s.partition(sep) | Always a 3-tuple (before, sep, after) — at the first sep |
s.rpartition(sep) | Same, at the last sep |
print(" a b c ".split()) # ['a', 'b', 'c']
print("a,,b,".split(",")) # ['a', '', 'b', '']
print("k=v=w".split("=", 1)) # ['k', 'v=w']
print("a.b.c.txt".rsplit(".", 1)) # ['a.b.c', 'txt']
print("one\ntwo\r\nthree\n".splitlines()) # ['one', 'two', 'three']
print("one\ntwo\n".split("\n")) # ['one', 'two', '']
print("user@example.com".partition("@")) # ('user', '@', 'example.com')
print("no-at-sign".partition("@")) # ('no-at-sign', '', '')
key, _, value = "timeout=30".partition("=")
print(key, value) # timeout 30Trimming & prefixes
print(" hi ".strip() + "|") # hi|
print("xxhixyx".strip("xy")) # hi ← a SET of characters, not a substring
print("www.python.org".lstrip("w.")) # python.org
print("test_login.py".removesuffix(".py")) # test_login
print("mississippi".rstrip("ip")) # mississ
print("mississippi".removesuffix("ippi")) # mississ
print("reader.txt".rstrip(".txt")) # reader ← looks right…
print("rat.txt".rstrip(".txt")) # ra ← …but eats the 't' of 'rat'
print("rat.txt".removesuffix(".txt")) # ratPadding & alignment
print("[" + "hi".center(8, "*") + "]") # [***hi***]
print("[" + "hi".ljust(6) + "]") # [hi ]
print("[" + "hi".rjust(6, ".") + "]") # [....hi]
print("42".zfill(5), "-42".zfill(5)) # 00042 -0042
print("a\tbc\td".expandtabs(4)) # a bc d
print("-" * 10) # ----------Replacing & translating
s = "a-b-c-d"
print(s.replace("-", "+")) # a+b+c+d
print(s.replace("-", "", 2)) # abc-d ← only the first 2
table = str.maketrans({"a": "4", "e": "3", "o": "0"})
print("hello world".translate(table)) # h3ll0 w0rld
strip_vowels = str.maketrans("", "", "aeiou") # 3rd arg: characters to delete
print("programming".translate(strip_vowels)) # prgrmmng
print("abc".translate(str.maketrans("abc", "xyz"))) # xyztranslate does many single-character replacements (and deletions) in one pass — much faster than chaining replace calls.
Character-class predicates
| Method | True when every character is… | '²' | '½' | '٣' (Arabic 3) |
|---|---|---|---|---|
isdecimal() | a decimal digit usable by int() | False | False | True |
isdigit() | a digit, including superscripts | True | False | True |
isnumeric() | any numeric character, incl. fractions | True | True | True |
for s in ["123", "²", "½", "٣", "-5", "3.5", ""]:
print(repr(s), s.isdecimal(), s.isdigit(), s.isnumeric())'123' True True True
'²' False True True
'½' False False True
'٣' True True True
'-5' False False False
'3.5' False False False
'' False False Falseprint("abc123".isalnum(), "abc".isalpha(), "ABC".isupper()) # True True True
print(" \t\n".isspace(), "".isspace()) # True False
print("my_var".isidentifier(), "2fast".isidentifier()) # True False
print(int("٣") + 1) # 4Comparison, repetition & membership
print("apple" < "banana", "Zebra" < "apple") # True True ← 'Z' (90) < 'a' (97)
print(sorted(["b", "C", "a"])) # ['C', 'a', 'b']
print(sorted(["b", "C", "a"], key=str.casefold)) # ['a', 'b', 'C']
print("10" < "9", int("10") < int("9")) # True False
print("ab" * 3, "-" * 0 == "") # ababab True
print("ell" in "hello", "" in "hello") # True TrueBuilding strings efficiently
nums = [3, 1, 4]
print(", ".join(map(str, nums))) # 3, 1, 4
print("".join(reversed("stressed"))) # desserts
try:
", ".join(nums)
except TypeError as e:
print(type(e).__name__) # TypeErrorInterview questions
What's the difference between find and index?
Why does 'rat.txt'.rstrip('.txt') return 'ra'?
lower() vs casefold()?
How do you reverse the words of a sentence?