Start with the study notes on Strings (definitions, examples and a quick revision), then work through 30 practice questions, each with the correct answer and a clear explanation of why it is right. When you are ready, take this topic as an interactive quiz to test yourself.
14 easy Β· 13 medium Β· 3 hard Β· Part of Python: Master Python from basics to advanced - 20 topics.
Topic overview
Strings β working with text
1. What is a string?
A string (str) is a sequence of characters, written in single, double or triple quotes. Strings are immutable: once created, they cannot be changed.
a = 'hello'
b = "hello"
menu = """1. Start
2. Quit"""
print(a == b)
print(menu)
OutputTrue
1. Start
2. Quit
2. Indexing
Each character has a position (index) starting at 0. Negative indexes count from the end.
s = "python"
print(s[0], s[2])
print(s[-1], s[-2])
print(len(s))
Outputp t
n o
6
3. Slicing
s[start:end:step] takes a piece of the string, up to but not includingend.
s = "python"
print(s[1:4])
print(s[:3], s[3:])
print(s[::2])
print(s[::-1]) # reversed
Outputyth
pyt hon
pto
nohtyp
Example: Palindrome check: s == s[::-1] is True for "madam".
4. Common string methods
Methods return a new string; the original is unchanged.
s = " Hello World "
print(s.strip())
print(s.strip().lower(), s.strip().upper())
print("hello world".title())
print("banana".replace("a", "o"))
print("banana".count("a"))
print("report.pdf".endswith(".pdf"))
print("123".isdigit(), "12.5".isdigit())
OutputHello World
hello world HELLO WORLD
Hello World
bonono
3
True
True False
5. split() and join()
split() cuts a string into a list of pieces.
join() glues a list of strings together with a separator.
print("a,b,c".split(","))
print("one two three".split())
words = ["a", "b", "c"]
print("-".join(words))
"py" in "python" tests whether a substring exists.
find() returns the position, or -1 if not found.
index() returns the position, but raises ValueError if not found.
s = "hello"
print("ll" in s)
print(s.find("ll"), s.find("xy"))
OutputTrue
2 -1
7. f-strings and format()
An f-string starts with f and fills in {expressions} inside the text. A format code after : controls the display, e.g. .2f for 2 decimal places.
name, age = "Ana", 21
print(f"Hello {name}, you are {age}")
print(f"Next year: {age + 1}")
price = 100
print(f"Total: {price * 1.18:.2f}")
print("Hello {}, you are {}".format(name, age))
OutputHello Ana, you are 21
Next year: 22
Total: 118.00
Hello Ana, you are 21
8. Joining, repeating and immutability
print("ab" * 3)
print("-" * 10)
s = "hello"
s = "H" + s[1:] # build a new string
print(s)
age = 21
print("Age: " + str(age))
Outputababab
----------
Hello
Age: 21
Remember:s[0] = "H" is a TypeError, because strings can't be changed in place. And "Age: " + 21 is also a TypeError: convert with str(), or use an f-string.
9. Characters and comparison
Strings compare alphabetically by character codes. ord() gives a character's number, and chr() does the reverse.
print("apple" < "banana")
print("Zoo" < "apple") # capitals come first
print(ord("A"), chr(66))
OutputTrue
True
65 B
10. Common misconceptions
Misconception
Correct understanding
s[1:4] includes index 4.
The end index is excluded: s[1:4] gives indexes 1, 2 and 3.
s.upper() changes s.
Strings are immutable; upper() returns a new string.
"Age: " + 21 works.
You cannot add str and int; use str(21) or an f-string.
find() raises an error when not found.
find() returns -1; index() is the one that raises ValueError.
\n is two characters.
\n is one character (a new line); len("a\nb") is 3.
11. Quick revision
Index
Position of a character, starting at 0.
Negative index
Counts from the end; -1 is the last character.
Slice
s[start:end:step]; end is excluded.
s[::-1]
The string reversed.
split()
Cuts a string into a list.
join()
Glues a list of strings together.
f-string
f"...{expr}..." fills in values.
Immutable
Cannot be changed after it is created.
12. Test your understanding
For s = "python", what is s[-1]?
Show answer
"n"
What does "python"[1:4] give?
Show answer
"yth"
How do you reverse a string s?
Show answer
s[::-1]
What does "a,b,c".split(",") return?
Show answer
['a', 'b', 'c']
What does "-".join(["a", "b"]) return?
Show answer
"a-b"
What does "hello".find("z") return?
Show answer
-1
How do you show a price with 2 decimal places in an f-string?
Show answer
f"{price:.2f}"
Why does s[0] = "H" fail?
Show answer
Strings are immutable; build a new string instead.
Key takeaway: Strings are immutable sequences: index from 0, slice with [start:end:step], and use methods, split/join and f-strings to build new text.
Notes written by Velnov. Every code example with an output was run in Python 3 to check that the output shown is exactly what Python prints.
.strip() removes whitespace (spaces, tabs, newlines) from BOTH ends of a string - the middle is untouched. lstrip() and rstrip() do only the left or right side.
Always strip() user input - people love typing stray spaces.
.replace(old, new) replaces EVERY occurrence by default: all three a's become o's -> 'bonono'. A third argument limits the count: replace("a", "o", 1) -> 'bonana'.
String methods
Q14.easy
What is the output of: print("py" in "python")
print("py" in "python") # True
print("java" in "python") # False
print("x" not in "python") # True
A True
B False
C 0
D Error
Answer: A β True
The in operator checks whether a substring exists inside a string: "py" appears at the start of "python", so True. It's the cleanest way to test 'contains'.
in operatorMembership testing
Q15.easy
name = "Ana"
Which line prints: Hello Ana! using an f-string?
name = "Ana"
print(f"Hello {name}!") # Hello Ana!
print("Hello {name}!") # Hello {name}! (no f!)
A print(f"Hello {name}!")
B print("Hello {name}!")
C print(f"Hello name!")
D print("Hello" + {name})
Answer: A β print(f"Hello {name}!")
An f-string starts with f before the quote and fills in {expressions}: f"Hello {name}!" -> Hello Ana!. Option B lacks the f, so it prints the braces literally.
f-strings (Python 3.6+) are the modern, preferred way to format text.
B find() returns -1 when not found; index() raises ValueError
C index() returns -1; find() raises an error
D find() only works on numbers
Answer: B β find() returns -1 when not found; index() raises ValueError
Both return the position of a substring. When the substring is absent, find() politely returns -1 while index() raises ValueError. Use find() when absence is normal.
f-string braces can hold ANY expression, not just variable names - it's evaluated and the result inserted: f"{2 + 3}" -> "5".
After a colon you can add formatting, e.g. :.2f = 2 decimal places.
f-stringsFormat specifiers
Q17.medium
What happens with:
s = "hello"
s[0] = "H"
s = "hello"
# s[0] = "H" # TypeError!
s = "H" + s[1:] # build a new string
print(s) # Hello
A s becomes "Hello"
B TypeError - strings are immutable
C s becomes "H"
D Nothing
Answer: B β TypeError - strings are immutable
Strings CANNOT be changed in place - assigning to a character raises TypeError. To 'change' a string you build a new one: "H" + s[1:].
Immutability is why all string methods RETURN a new string.
ImmutabilitySlicing
Q20.medium
Which expression checks if a filename ends with ".pdf"?
f = "report.pdf"
print(f.endswith(".pdf")) # True
print(f.startswith("rep")) # True
A filename.endswith(".pdf")
B filename.end(".pdf")
C filename[-4] == ".pdf"
D filename.last(".pdf")
Answer: A β filename.endswith(".pdf")
.endswith() and .startswith() test the ends of a string and return True/False. Option C is close but wrong - filename[-4] is a single character; you'd need filename[-4:].
.isdigit() is True when every character is a digit 0-9. Great for validating input BEFORE calling int(). "12.5".isdigit() is False (the dot isn't a digit).
isalpha()Input validation
Q23.medium
What is the output of: print("apple" < "banana")
print("apple" < "banana") # True
print("Zoo" < "apple") # True! capitals come before lowercase
A True
B False
C Error
D 5
Answer: A β True
Strings compare alphabetically (by character codes), letter by letter: 'a' < 'b', so "apple" < "banana" is True. This is why sorting a list of strings gives alphabetical order.
All UPPERCASE letters sort before all lowercase in default comparisons.
Orderingsorted()ord()
Q26.medium
What is the output of:
age = 21
print("Age: " + age)
age = 21
print("Age: " + str(age)) # works
print(f"Age: {age}") # best
print("Age:", age) # also works
A Age: 21
B TypeError - can't concatenate str and int
C Age: "21"
D Age:21
Answer: B β TypeError - can't concatenate str and int
+ can't join a string with a number. Fix it with str(age), an f-string, or a comma in print (which handles any type).
TypeErrorf-stringsstr()
Q27.medium
What is the output of: print("Hello {}, you are {}".format("Ana", 21))
print("Hello {}, you are {}".format("Ana", 21))
# same as:
name, age = "Ana", 21
print(f"Hello {name}, you are {age}")
A Hello Ana, you are 21
B Hello {}, you are {}
C Hello 21, you are Ana
D Error
Answer: A β Hello Ana, you are 21
.format() fills the {} placeholders in order: first {} gets "Ana", second gets 21. f-strings do the same job more readably, but .format() is common in older code.
format()f-strings
Q29.medium
Which expression removes only the TRAILING newline from s = "data\n"?
line = "data\n"
print(repr(line.rstrip())) # 'data'
A s.rstrip()
B s.strip("data")
C s.replace("n", "")
D s.cut()
Answer: A β s.rstrip()
.rstrip() strips whitespace (including \n) from the right end only - the standard way to clean lines read from a file. Option C would delete the letter n from 'data' too!
strip()Reading files
Hard questions (3)
Q24.hard
What do ord("A") and chr(66) return?
print(ord("A")) # 65
print(chr(66)) # B
print(chr(ord("a") + 1)) # b
A 65 and "B"
B "A" and 66
C 1 and "66"
D Error for both
Answer: A β 65 and "B"
ord() gives a character's Unicode number (A = 65) and chr() does the reverse (66 = B). They're inverses: chr(ord("A")) is "A" again.
Used in Caesar ciphers and character math puzzles.
\n is ONE character (the newline), not two. So the string contains 'a', newline, 'b' - length 3.
Escape sequenceslen()
Q30.hard
s = "madam" - which expression checks if s is a palindrome?
s = "madam"
print(s == s[::-1]) # True
s = "python"
print(s == s[::-1]) # False
A s == s[::-1]
B s.palindrome()
C s == reverse(s)
D s[::-1] == True
Answer: A β s == s[::-1]
A palindrome reads the same backwards. s[::-1] is the reversed string, so comparing it to the original does the check in one line. There's no built-in palindrome() or reverse() function for strings.