Python String Slicing and Methods: Split, Strip, Find, Join
Python string slicing takes a start, a stop and a step; a negative step reverses. The methods for case, whitespace, searching, splitting, joining and replacing.
- Course: Python study plan
- Module: Strings and text
- Kind: Lesson
- Reading time: 14 min
- Runtime: CPython 3.11
How does string slicing work in Python?
Python string slicing, s[start:stop:step], returns a new string from index start up to but not including stop, taking every step-th character. Each part is optional, negative indexes count from the end, and out-of-range bounds clip instead of raising: s[:3] is the first three characters, s[-3:] the last three and s[::-1] the string reversed.
Lesson
Two things make Python string handling short: slicing, which extracts any substring, reversal or every-other-character in one expression, and a method set that covers case, whitespace, searching, splitting, joining, testing and padding without a library. This lesson gives the slice rule precisely — it is the same rule for lists and tuples — and then the methods grouped by what they do, with the return-value conventions (find returns −1, index raises) that decide which one to call.
Slicing
s[start:stop:step] — start included, stop excluded, step the stride; each part optional; negative indexes count from the end; out-of-range bounds clip rather than raise.
s = "abcdefg"
s[1:4] # 'bcd'
s[:3] # 'abc' — from the start
s[3:] # 'defg' — to the end
s[-3:] # 'efg' — last three
s[:-1] # 'abcdef' — all but the last
s[::2] # 'aceg' — every second
s[::-1] # 'gfedcba' — reversed
s[1:100] # 'bcdefg' — clipped, no error
s[5:2] # '' — empty, no error
The half-open rule means s[:k] + s[k:] == s for any k, and the length of s[a:b] is b - a when in range. s[::-1] is the idiom for reversing a string (and "".join(reversed(s)) the readable alternative). A slice always returns a new string; slicing a list returns a new list (Module 6) — the syntax is identical.
Case and whitespace
"Hello World".lower() # 'hello world'
"hello".upper() # 'HELLO'
"hello world".title() # 'Hello World'
"hello".capitalize() # 'Hello'
"Straße".casefold() # 'strasse' — the aggressive lowercase for comparisons
" pad ".strip() # 'pad'
" pad ".lstrip() # 'pad '
"xxhixx".strip("x") # 'hi' — the argument is a *set* of characters, not a prefix
"file.txt".removesuffix(".txt") # 'file' (3.9); removeprefix likewise
strip() with no argument removes all whitespace (spaces, tabs, newlines) from both ends. With an argument it removes any of those characters, repeatedly, from both ends — "www.example.com".strip("w.") gives 'example.com', and "hello.py".strip(".py") gives 'hello' only by luck ('happy.py'.strip('.py') gives 'ha'). For a literal prefix or suffix, removeprefix/removesuffix.
Searching
s = "banana"
s.find("an") # 1 — first index, or -1
s.rfind("an") # 3 — last
s.index("an") # 1 — like find, but raises ValueError when absent
s.count("an") # 2 — non-overlapping
s.startswith("ba") # True
s.endswith(("na", "xa")) # True — a tuple tests several suffixes
"an" in s # True — the existence test; cheaper than find != -1
Use in when you only need yes/no; find when you need the position and absence is normal; index when absence is a bug you want raised. find and friends take optional start/end bounds: s.find("a", 2).
Splitting and joining
"a b c".split() # ['a', 'b', 'c'] — any whitespace, runs collapsed, ends trimmed
"a,b,,c".split(",") # ['a', 'b', '', 'c'] — exact separator, empties kept
"a,b,c".split(",", 1) # ['a', 'b,c'] — at most 1 split
"a,b,c".rsplit(",", 1) # ['a,b', 'c'] — from the right
"k=v=w".partition("=") # ('k', '=', 'v=w') — always a 3-tuple; ('k=v=w', '', '') if absent
"one\ntwo\n".splitlines() # ['one', 'two'] — no trailing empty element
", ".join(["a", "b"]) # 'a, b'
"".join(reversed("abc")) # 'cba'
split() with no argument is the tokeniser for whitespace-separated input; split(sep) is for delimited fields where empty fields matter (CSV-like lines). partition is the tool for "the part before the first = and the part after" and never raises. join requires an iterable of strings: ",".join([1, 2]) is a TypeError, so map with str first.
Replacing and translating
"a-b-c".replace("-", "+") # 'a+b+c'
"a-b-c".replace("-", "+", 1) # 'a+b-c' — at most once
table = str.maketrans("abc", "xyz")
"aabbcc".translate(table) # 'xxyyzz' — character-for-character, in one pass
"hello".translate(str.maketrans("", "", "lo")) # 'he' — the third argument deletes
replace is for substrings; translate is faster for many single-character substitutions or deletions (removing punctuation, for instance) because it makes one pass with a table.
Testing
"123".isdigit() # True
"abc".isalpha() # True
"ab1".isalnum() # True
" ".isspace() # True
"Hello".isupper() # False
"hello".islower() # True
"Hello World".istitle() # True
isdigit is true for "²" and false for "-1" and "1.5", so it is a check for "all digit characters", not for "parses as a number" — for that, try int() and catch ValueError (Module 2 lesson 5). The next lesson separates isdigit, isdecimal and isnumeric.
Padding and alignment
"42".zfill(5) # '00042'
"-42".zfill(5) # '-0042' — sign-aware
"ab".ljust(5, ".") # 'ab...'
"ab".rjust(5) # ' ab'
"ab".center(6, "*") # '**ab**'
Format specs (next lesson) do the same inside an f-string — f"{'ab':.<5}" — and are what you use when the padding is part of a larger line.
Pitfalls
strip(".txt")as a suffix remover. It strips characters; useremovesuffix.split(" ")for whitespace tokenising — it keeps empty strings between consecutive spaces; usesplit().indexon a value that may be absent, raisingValueError; usefindorin.joinon a list of non-strings.s.find(x) == True—findreturns a position;1 == Truebut0 != True.- Expecting
title()to handle apostrophes ("it's"→"It'S").
Key takeaways
s[a:b:c]— half-open, negative indexes from the end, clipping bounds,[::-1]reverses.strip/lstrip/rstripremove characters from a set at the ends;removeprefix/removesuffixremove a literal.infor existence,findfor a position or −1,indexto raise;count,startswith/endswithwith tuples.split()tokenises whitespace,split(sep)keeps empties,partitionis a 3-tuple,joinneeds strings.replacefor substrings,translatefor many characters;is*test character classes;zfill/ljust/rjust/centerpad.
Common questions
How do I reverse a string in Python?
Slice it with a step of -1: s[::-1] returns the characters in reverse order as a new string. "".join(reversed(s)) is the more readable alternative. Strings are immutable, so both build a new string rather than reversing the original in place.
What is the difference between strip and removesuffix in Python?
strip(chars) removes any of the given characters, repeatedly, from both ends — its argument is a set of characters, not a word — so "happy.py".strip(".py") gives "ha". removesuffix(".py") and removeprefix, added in Python 3.9, remove one literal suffix or prefix if it is present.
What is the difference between find and index in Python?
Both return the position of the first occurrence of a substring. When it is absent, find returns -1 and index raises ValueError. Use in when you only need yes or no, find when absence is normal, and index when absence is a bug you want raised.
What is the difference between split() and split(" ") in Python?
split() with no argument splits on any run of whitespace and drops leading and trailing whitespace, so "a b c".split() is ["a", "b", "c"]. split(" ") splits at every single space and keeps the empty strings between consecutive spaces. Use split(sep) when empty fields matter, as in comma-separated lines.
Exercises
Slice commands
Read a string, then n commands, and print the result of each slice: rev reverses; every k takes every k-th character from the start; first k and last k take that many characters; drop k removes the first k; mid removes the first and last character. Every answer is one slice expression.
Input: the string, then n, then n commands. Output: one line per command (an empty result prints (empty)).
abcdefg
4
rev
every 2
last 3
drop 2
prints
gfedcba
aceg
efg
cdefgSlugs
Turn titles into URL slugs without regular expressions: casefold the text, replace every character that is not a letter or digit with a hyphen, collapse runs of hyphens into one, and strip hyphens from both ends. Build the result character by character or with split/join.
Input: lines of titles. Output: one slug per line, or (empty) when nothing remains.
Hello, World!
Python 3.11 is here
prints
hello-world
python-3-11-is-hereIn this module: Strings and text
- String basics — an immutable sequence of characters
- Slicing and the string methods (this lesson)
- Formatting — f-strings and the format-spec mini-language
- Characters, code points, bytes and Unicode
- Parsing input — from lines and tokens to values
- Regular expressions — the re module
- Checkpoint — Strings and text
← String basics — an immutable sequence of characters · Formatting — f-strings and the format-spec mini-language →