Topic 1.5
Strings: The Basics
In one line
A string (str) is a piece of text: a sequence of characters between quotes. You can measure it with len, pick characters by position, join and repeat strings, and test whether one is inside another. A string can never be changed in place.
Think of it like this
Beads on a thread. Each bead is one letter, and the threaded beads in order make a word. You can count the beads, point at the third one, or join two threads. You cannot repaint a bead on the thread: to change the word you thread a new one. A Python string works like that.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- String (str)
- A sequence of characters, i.e. text, written between quotes.
- Character
- One letter, digit, symbol or space in a string.
- Index
- The position of a character in a string, counting from 0.
- Escape sequence
- A backslash plus a letter that stands for a special character, such as
\nfor a new line. - Raw string
- A string with an
rbefore the quote, where backslashes are kept as typed. - Concatenation
- Joining strings end to end with
+. - Immutable
- Cannot be changed after it is created.
- Unicode
- The worldwide standard that gives every character from every language a number.
Step by step
01Quotes
Single and double quotes make exactly the same string. The only reason to prefer one is to avoid a backslash: "It's fine" is easier than 'It\'s fine'. Whichever kind opens the string must also close it.
Triple quotes keep line breaks exactly as typed. They are also used for long messages and for documentation text (Topic 1.11).
a = 'single'
b = "double"
c = "It's fine"
d = 'She said "hi"'
poem = """Roses are red,
Violets are blue."""
print(a, b, c, d)
print(poem)02Escapes and raw strings
Inside a normal string, a backslash plus a letter has a special meaning. print("Line one\nLine two") shows two lines. If you want a real backslash, type two.
A Windows path such as C:\new\table would break, because \n and \t become a new line and a tab. A raw string r"C:\new\table" keeps every backslash as typed.
print("Line one\nLine two")
print("Tab\tseparated")
print("A backslash: \\")
print(r"C:\new\table")03Length and index
Think of the string as numbered slots: P=0, y=1, t=2, h=3, o=4, n=5. len is 6 because there are six characters, but the last index is 5. This off-by-one difference is behind many beginner bugs.
Negative indexes count backwards, so word[-1] is always the last character, whatever the length.
word = "Python"
print(len(word)) # 6
print(word[0], word[5]) # P n
print(word[-1], word[-2]) # n o04Join, repeat and test
+ and * on strings do what they mean in plain English: join and repeat. "-" * 20 is a quick way to draw a line. in is a yes/no question, so it gives a bool.
print("Py" + "thon", "ab" * 3, "-" * 20)
print("th" in "Python", "x" in "Python") # True False05Strings cannot be changed
word[0] = "J" tries to repaint a bead, and Python refuses. Instead, build a new string from pieces: "J" + word[1:] means "J, then everything from index 1 onwards" (slicing is covered in Topic 3.1). The old string is untouched.
Immutability is what makes strings safe to share and to use as dictionary keys (Phase 4). It also means that building a long string with many + steps creates many temporary strings: Topic 3.5 shows a faster way.
word = "Python"
fixed = "J" + word[1:]
print(fixed, word) # Jython Python
word[0] = "J" # TypeError06Characters are numbers underneath
Every character has a number called its code point. ord("P") gives 80 and chr(80) gives back "P". The number belongs to Unicode, so it does not depend on your computer. A character that looks like one symbol (like an emoji) is usually one code point, so len("😀") is 1.
Try it yourself
- 1
Count the slots
For
word = "Hectal", predictlen(word),word[0],word[-1]andword[3]. Then run them. - 2
Draw a box edge
Print
"+" + "-" * 10 + "+". Change the 10 to see the line grow. - 3
A path with backslashes
Print
"C:\new\table"without therand see what happens to\nand\t. Then add ther.
Code & diagrams
The last line shows that len counts characters (code points), not bytes.
Expected output
single double It's fine She said "hi"
Line one
Line two
Tab separated
A backslash: \
C:\new\table
Roses are red,
Violets are blue.
6 P n n o
Python ababab --------------------
True False
5 1 0Methods return new strings. The last line fails on purpose.
Expected output
Python PYTHON
Jython Python
P 80 P
Traceback (most recent call last):
File "main.py", line 9, in <module>
word[0] = "J"
~~~~^^^
TypeError: 'str' object does not support item assignmentBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Index past the end
Ask for the character at index 6 of "Python".
word = "Python"
print(word[6])Break #2
Quotes inside quotes
Put double quotes inside a double-quoted string.
message = "She said "hello""Myth vs fact
Myth
Single quotes are for characters and double quotes are for strings.
Fact
Python has no separate character type. A single character is a string of length 1, and both kinds of quotes make the same str.
Myth
word.upper() changes word.
Fact
Strings are immutable. .upper() returns a new string and leaves word alone; you must save the result with a name.
Myth
The index of the first character is 1.
Fact
Python counts from 0. The first character is s[0], the last is s[len(s) - 1] or s[-1].
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
A CPython
strstores its characters compactly: 1 byte per character if all are in Latin-1, 2 bytes if they fit in 16 bits, otherwise 4 bytes (PEP 393). A string of plain English costs about 1 byte per character plus a small header. - ▸
Because strings are immutable and hashable, they are the usual dictionary key (a
strcaches its hash after the first computation), and CPython caches (interns) short identifier-like strings. Do not rely onisfor strings, even when it seems to work. - ▸
lencounts code points, not what a reader sees as one character.len("e\u0301")is 2 (aneplus a combining accent, which looks like one letter), and a family emoji built from several code points can have alenof 5. Compare such text only after normalising it withunicodedata.normalize("NFC", s)(Topic 3.4). Also, indexing astris O(1) because CPython stores fixed-width characters, which is why PEP 393 uses 1, 2 or 4 bytes for the whole string, never a mixture. - ▸
Repeated
s = s + piecein a loop can be slow for very long strings. Collect pieces and use"".join(pieces)instead (Topic 3.5). - ▸
LLMs (large language models, the AI behind chatbots) read text as tokens, small pieces of text that are often part of a word, not characters. The string
len()of a prompt is not its token count, so API code uses a tokenizer to count and cut prompts (Phase 16).
Remember this
- 1
A string is text written between quotes:
'single'or"double"both work and mean the same. Use whichever lets you include the other kind inside:"It's fine"and'She said "hi"'. The type is calledstr. An empty string""has no characters. - 2
A backslash starts an escape sequence, a way to type a character you cannot type directly.
\nis a new line,\tis a tab,\\is one backslash, and\"is a quote. A raw string, writtenr"C:\new\table", switches escapes off, which is useful for Windows paths and for patterns (Topic 3.6). Triple quotes,"""...""", let a string run over several lines. - 3
len(s)gives the number of characters. Each character has a position called its index, and Python counts from 0. In"Python",word[0]isPandword[5]isn. Negative indexes count from the end:word[-1]is the last character. An index beyond the end is anIndexError. Slices such asword[1:]come in Topic 3.1. - 4
+joins two strings (concatenation):"Py" + "thon"is"Python".*repeats:"ab" * 3is"ababab".intests whether one string appears inside another:"th" in "Python"isTrue. Joining a string and a number with+is an error. You must convert first (Topic 1.6) or use an f-string (Topic 1.9). - 5
Strings are immutable: once made they cannot be changed.
word[0] = "J"raises aTypeError. Methods such as.upper()(a method is a function that belongs to a value and is called with a dot, likeword.upper(); Topic 3.2) do not change the string; they return a new one. To "change" a string you build a new string and point the name at it. - 6
Python 3 strings hold Unicode characters, so
"naïve","नमस्ते"and"😀"are all normal strings, andlen("😀")is 1. Topic 3.4 explains how that text is turned into bytes with encodings such as UTF-8.
Explain it without notes
What does it mean that a Python string is immutable, and how do you "modify" one?
How does string indexing work? What do s[0], s[-1] and len(s) give?
What are escape sequences and raw strings for?
What happens if you write "Age: " + 5, and how do you fix it?
Practice
Store your name in a variable, then print its length, its first letter and its last letter.
Print a line of 30 equals signs without typing them one by one.
Check whether the text "cat" appears in "concatenate", and print the answer.
Trade-offs
- ↔
Immutability vs. convenience. Immutable strings are safe to share and hash, but you cannot edit them in place; changing text always means building a new string.
- ↔
Escapes vs. raw strings. Raw strings make paths and patterns readable, but cannot end with a single backslash and give up escapes like
\n.
Done when you can
Done when you can write a string with single, double and triple quotes.
Done when you can use
\n,\tand a raw string correctly.Done when you can predict
s[0],s[-1]andlen(s)for a given string.Done when you can explain why
word[0] = "J"fails and how to get "Jython".Done when you can read an
IndexError: string index out of range.