String methods reference
Every string method that matters, grouped by task — cleaning, searching, splitting, and formatting.
Why this matters in AI / ML / GenAI
Text preprocessing is most of the work in any NLP or LLM pipeline. Prompt templates, log parsing, and cleaning scraped data are all string methods, and doing them correctly is faster and more readable than reaching for regex.
Cleaning and case
Strings are immutable — every method returns a new string and the original is unchanged. Forgetting to assign the result is the most common string bug: text.strip() on its own does nothing.
strip(),lstrip(),rstrip()— remove whitespace, or any characters you passlower(),upper(),title(),capitalize(),swapcase()casefold()— aggressive lowercasing for cross-language comparison; prefer it overlower()when comparing user inputremoveprefix(),removesuffix()— safer than slicing, since they do nothing when the affix is absent
Note that strip("abc") removes any of those characters from the ends, not the substring "abc". That trips people up.
Searching and testing
in— the simplest containment check, and usually the right onefind()returns -1 when missing;index()raisesValueErrorstartswith(),endswith()— both accept a tuple of optionscount()— non-overlapping occurrencesreplace(old, new, count)— the optional count limits replacements
Validation predicates: isdigit(), isalpha(), isalnum(), isspace(), islower(), isupper(), istitle().
Watch out: "3.14".isdigit() is False because of the dot, and "-5".isdigit() is False because of the sign. For numeric validation, try converting inside a try/except instead.
Splitting, joining, and formatting
split() with no argument splits on any run of whitespace and drops empties — usually what you want for text. split(",") splits on an exact delimiter and keeps empty fields. splitlines() handles all newline conventions.
"".join(parts) is the correct way to build a string from pieces. Repeated += in a loop creates a new string every iteration and is quadratic on large inputs.
partition(sep) returns exactly three parts (before, separator, after), which makes it cleaner than split for "key=value" parsing.
f-strings are the modern format: f"{value:.2f}", f"{n:,}", f"{text:>10}", f"{ratio:.1%}". Add = for debugging: f"{score=}" prints both the name and the value.
For alignment use ljust, rjust, center, or zfill for zero-padded numbers.
Copy-paste examples
Copy into your own editor, or load one into the compiler below and press Run.
Cleaning user and scraped text
Strings are immutable — you must assign the result.
raw = " Hello, GenAI World!\t\n"
print(repr(raw))
print(repr(raw.strip()))
print(repr(raw.strip().lower()))
raw.strip() # result discarded — a very common bug
print("original unchanged:", repr(raw))
path = "logs/model-run.json"
print("\nremovesuffix:", path.removesuffix(".json"))
print("removeprefix:", path.removeprefix("logs/"))
print("missing affix is a no-op:", path.removesuffix(".csv"))
print("\nstrip('/-') strips characters, not the substring:")
print(repr("--/api/users/--".strip("/-")))
print("\ncasefold beats lower for comparison:", "STRASSE".casefold() == "strasse".casefold())Searching and validating
find returns -1, index raises. isdigit is stricter than people expect.
text = "model=gpt-4.1-mini temperature=0.2 stream=true"
print("'temperature' in text ->", "temperature" in text)
print("find('stream') ->", text.find("stream"))
print("find('missing') ->", text.find("missing"), "(-1, no exception)")
print("count('=') ->", text.count("="))
print("startswith tuple ->", text.startswith(("model", "engine")))
print("\nvalidation predicates:")
for candidate in ["42", "3.14", "-5", "abc", "a1", " "]:
print(f" {candidate!r:<8} isdigit={candidate.isdigit()!s:<6} "
f"isalpha={candidate.isalpha()!s:<6} isalnum={candidate.isalnum()}")
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
print("\nreliable numeric check:", {s: is_number(s) for s in ["42", "3.14", "-5", "abc"]})Splitting and joining
partition is cleaner than split for key=value pairs.
line = "model=gpt-4.1-mini,temp=0.2,stream=true"
settings = {}
for chunk in line.split(","):
key, sep, value = chunk.partition("=")
if sep:
settings[key] = value
print(settings)
print("\nsplit() vs split(','):")
print(" ", "a b c".split())
print(" ", "a,,b".split(","), "(keeps the empty field)")
print(" ", "a,b,c".split(",", maxsplit=1), "(maxsplit)")
log = "line one\nline two\r\nline three"
print("\nsplitlines handles all newline styles:", log.splitlines())
parts = ["retrieve", "rerank", "generate"]
print("\njoined:", " -> ".join(parts))
print("csv row:", ",".join(str(x) for x in [1, 2.5, "text"]))f-string formatting specifiers
The specifiers you will reuse constantly in reports and logs.
score = 0.9137
tokens = 1234567
name = "mini"
print(f"2 decimals : {score:.2f}")
print(f"percent : {score:.1%}")
print(f"thousands : {tokens:,}")
print(f"scientific : {tokens:.2e}")
print(f"plus sign : {score:+.3f}")
print(f"pad left : |{name:>10}|")
print(f"pad right : |{name:<10}|")
print(f"centred : |{name:^10}|")
print(f"fill char : |{name:*^10}|")
print(f"zero padded : {7:03d}")
print(f"\ndebug form : {score=}")
print(f"repr in field: {name!r}")
width = 8
print(f"dynamic width: |{name:>{width}}|")
print("\nold ways still work:")
print("percent style: %.2f" % score)
print("str.format : {:.2f}".format(score))Building an aligned report
ljust, rjust, and zfill for table output without a library.
rows = [("gpt-4.1-mini", 0.913, 620), ("llama-3-8b", 0.847, 1520), ("claude-haiku", 0.900, 460)]
header = f"{'model'.ljust(16)}{'accuracy'.rjust(10)}{'tokens'.rjust(9)}"
print(header)
print("-" * len(header))
for model, acc, tokens in rows:
print(f"{model.ljust(16)}{f'{acc:.3f}'.rjust(10)}{f'{tokens:,}'.rjust(9)}")
print("\nzfill for ids:", [str(i).zfill(4) for i in [1, 42, 999]])
print("centred title:", "SUMMARY".center(35, "="))
print("wrapped label:", "retrieval".upper().ljust(20, "."), "OK")Clean and parse a messy log line
Try it — in-browser Python
Add another key=value pair to the raw line and it parses automatically.
Output
Python runs in your browser. First run downloads the runtime.
Press Run (or Ctrl+Enter) to execute.
CPython in WebAssembly. Stdlib works. NumPy, pandas, scikit-learn and Matplotlib load on demand, and charts render below. No input(), no GPU, no network installs.
Takeaways
- Strings are immutable — always assign the result of a method call.
- Use join to build strings, partition for key=value, and split() bare for whitespace.
- f-string specifiers (.2f, :,, :.1%, alignment) cover almost all formatting needs.