Strings: Beginner
A string is a run of characters that Python keeps in order, from first to last: the letters of a city name, the digits of a postcode, a whole paragraph of an email. You write one by placing the text between quotes. The quotes mark where the text starts and stops, and they're not stored with the value: "Oslo" holds 4 characters, the capital O and the 3 small letters after it.
Python accepts either double quotes or single quotes, and the value is the same either way: the last line prints True because both literals hold the same 4 characters. The type of every string is str, and the third line confirms it: type(city) == str is True. Pick one quote style for a program and keep to it, so a reader scanning your code sees the same shape on every line.
Text that looks like a number
Putting digits between quotes makes a string. "42" is 2 characters that happen to be digits, and 42 is an integer the computer can add and multiply. They're stored differently and never compare equal, so a value that arrives from a form field or a spreadsheet cell as text stays text until something converts it. Arithmetic works on the integer and leaves the string alone.
| Literal | Type | What it holds |
|---|---|---|
| "42" | str | 2 characters, the digits 4 and 2 |
| 42 | int | the integer 42 |
| "" | str | 0 characters, the empty string |
| " " | str | 1 character, a space |
| "True" | str | 4 characters, a word rather than the boolean True |
A ZIP code such as "02134" must stay a string: stored as the integer 2134 it loses its leading zero and the address lookup fails. Phone numbers behave the same way, and so do product codes and account identifiers. In data work, if you would never add 2 of them together, keep them as strings.
Walking through the characters
A for loop over a string visits its characters one at a time, in order, the same way a loop over range(4) visits the numbers 0 through 3. Each pass hands the loop variable 1 character, which is itself a tiny string holding that single character. Counting the passes tells you how many characters the string has, and the animation below does that for "Oslo".
1word = "Oslo"2count = 03for ch in word:4 count = count + 15 print(ch)6print("characters:", count)
ch takes each character of word in order, and count goes up by 1 per pass.
The loop body ran 4 times, so count finished at 4 and the last line printed characters: 4. Run the same loop over the empty string "" and the body never executes: count stays 0 and only the final line is printed. A space is a character like any other, so "New York" counts to 8, including the gap between the words.
Equal means every character matches
Two strings compare equal with == only when they hold the same characters in the same order. Python checks them one position at a time, and a capital letter is a different character from its small form, so "Oslo" == "oslo" is False. A trailing space counts too: "Oslo " has 5 characters and never equals the 4-character "Oslo", even though both look alike on screen.
What does this program print?
Counting works the same whatever kind of characters a string holds. Every character gives the loop 1 pass, spaces and punctuation included, so the product code "X9-7" counts to 4 and the postcode "02134" counts to 5. The loop visits each character in turn without looking at what kind it is.
Some text runs across several lines: an email body, a receipt, the help message of a command. A string can span as many lines as you like if you open and close it with 3 quotes in a row. Both """ and ''' work, and every line break you type between the opening and closing quotes is stored as part of the string. The string ends only at the matching 3 quotes.
One print call produced 3 lines because the string itself contains a line break after shipped. and another after Thursday.. Nothing special happened at print time: print wrote the characters it was given, and 2 of those characters moved the cursor to the next line.
A line break is a character
The string starts right after the quotes
Pressing Enter straight after the opening """ puts a line break at the very start of the string, so the first thing printed is an empty line. This is the most common surprise with triple quotes. The program below prints a blank line before Welcome, and done shows where the string ended.
To begin with Welcome on the first printed line, type it on the same line as the opening quotes, as the shipping message above does. Likewise, a line break before the closing quotes adds a trailing blank line to whatever you print.
Indentation inside the quotes is kept
The content of a string is text rather than code, so Python does not require it to be indented. Writing Paid: 40 flush against the left margin, inside the function, removes the leading spaces while the rest of the function stays indented as usual. It looks odd in the editor and prints correctly.
You have met triple quotes already: a docstring is a triple-quoted string written as the first statement of a function, and it keeps the line breaks you type like any other. Its later lines can still sit at the function body's indentation, because documentation tools strip the indentation those lines share before showing the text, and Python itself does the same when it stores a docstring from version 3.13 onward. An ordinary triple-quoted string such as the receipt above gets no such treatment, so its leading spaces stay.
Multiline strings in pipeline code
- Starts and ends on the same source line
- A line break before the closing quote is a syntax error
- Fits anything that stays on one line, like a name or a sentence
- Can run across many source lines
- Every typed line break and leading space is stored
- Fits docstrings and any message or query that runs past one line
How many characters does the loop count?
Returning a multiline message
A function can build a multiline string and hand it back with return, and the caller prints it like any other value. The same rules apply inside the function: the text starts with whatever follows the opening quotes, so the first line of the message goes right after them. Continuation lines sit at the left margin, because spaces typed before them would be stored.
The output has exactly 2 lines of message and no blank line above them, because Meeting at 10 begins on the line of the opening quotes and Room 4B begins at column 0. Move Meeting at 10 down a line and the printed message would open with an empty line.
The + operator joins 2 strings end to end and gives back a new string containing both. Nothing is inserted between them: if you want a space, you concatenate a space. Swapping the operands changes the result, so "Ada" + "Lovelace" is a different string from "Lovelace" + "Ada".
Each of the 3 expressions produces a new string. first and last are unchanged afterwards. + reads the strings it is given and produces a fresh result, which you then print or store in a variable. The strings you started with are never modified.
Growing a string in a loop
Because + returns a new string, building text piece by piece means assigning the result back to the same variable on each pass. The animation walks the digits of a date code and attaches each one to label with a dash in front of it, while day keeps its original value throughout.
1day = "0301"2label = "d"3for ch in day:4 label = label + "-" + ch5 print(label)6print(day)
label gets a new, longer value on every pass, while day stays 0301.
Each pass replaces label with a longer string. It starts as d-0 and grows through d-0-3 and d-0-3-0 until it reaches d-0-3-0-1. The last line prints 0301, confirming that reading characters from day left it as it was. This assign-back pattern, label = label + something, is how you build a CSV row from its fields, and report lines and log messages get assembled the same way.
Repeating with *
Multiplying a string by an integer repeats it that many times, which is the quickest way to draw a separator or pad a column. "-" * 10 is 10 dashes, and "ab" * 3 is ababab. Multiplying by 0 gives the empty string. As with numbers, * runs before +, so "=" * 3 + "end" repeats first and joins second.
Only strings join strings
+ between a string and a number stops the program. Python won't guess whether you wanted Order 42 or arithmetic, so it raises a TypeError and the lines after it never run. The error message names both types, which is how you find the mistake in a longer program.
You already have a tool that prints mixed values side by side: print with commas. It accepts strings and numbers alike and puts 1 space between each pair. Use + when you need the joined text as a value you can store or return, and commas when all you need is to display it.
- Produces a value you can store or return
- Adds nothing between the pieces
- Every piece must be a string
- Displays the values and produces nothing
- Puts 1 space between the pieces
- Accepts strings mixed with ints or floats
What does this program print?
A count in a variable sets the repeats
The number on the right of * can come from a variable, which lets a count decide how long a piece of text is. Here a string and an int meet in one expression without an error: * accepts an int and repeats the text, while + refuses one. A string on both sides of * fails the other way, with TypeError: can't multiply sequence by non-int of type 'str'.
Both pieces of bar are computed first, because * runs before +, and then the brackets are concatenated around the result. Change done to 4 and left to 1 and the bar redraws as [####.] with no other edit.
| Escape | Stands for | Example | Printed |
|---|---|---|---|
| \n | line break | "a\nb" | a, then b on the next line |
| \t | tab | "a\tb" | a, a jump to the next tab stop, b |
| \" | double quote | "say \"hi\"" | say "hi" |
| \' | single quote | 'it\'s' | it's |
| \\ | one backslash | "C:\\temp" | C:\temp |
The tab is the odd one out: it moves the cursor to the next tab stop, usually every 8 columns, rather than inserting a fixed number of spaces. Short values followed by \t therefore line up in the same column, which is handy for a quick table printed to the screen.
An escape sequence is 1 character
You type 2 symbols, but the string stores 1 character. "a\nb" has 3 characters, and "C:\\temp" has 7, with a single backslash sitting between the colon and the t. A loop that counts characters confirms both figures.
Triple quotes write \n for you
The line breaks you typed inside triple quotes in the previous section are these same \n characters. A 2-line triple-quoted string and a string written with one pair of quotes and \n in the middle are equal, character for character. Choose triple quotes when the text is long enough that seeing its shape helps, and \n when the string is short or built from parts with +.
Backslashes in a pasted Windows path
A backslash in text you paste from elsewhere, a Windows folder path for instance, is read as the start of an escape. "C:\new folder" contains \n, so the path breaks across 2 lines when printed and the letter n is gone. Doubling every backslash restores the intended characters.
- Double a backslash that should appear in the output
- Use \n for a short 2-line string built with +
- Switch quote styles before reaching for \" or \'
- Paste a path with backslashes into a string unchanged
- Count an escape as 2 characters
- Expect \t to insert a fixed number of spaces
How many characters does the loop count?
Several escapes in one string
Between its quotes the source line has 29 typed symbols, and the loop counts 24 characters: each of the 5 escapes was typed as 2 symbols and stored as 1. The tab after Plays: puts 12 in the same column as the quoted name, because both labels end before the first tab stop.
A string carries a set of built-in operations called methods. You call one by putting a dot after the string and then the method name with parentheses, the same way you call a function you defined with def, except the string comes first. name.upper() asks the string in name for a copy of itself with every letter in capitals. The 5 case methods below are the ones you will use most.
| Call on "hello World" | Result | Rule |
|---|---|---|
| upper() | HELLO WORLD | every letter to capitals |
| lower() | hello world | every letter to small |
| capitalize() | Hello world | first character up, the rest down |
| title() | Hello World | first letter of each word up, the rest down |
| swapcase() | HELLO wORLD | each letter flipped |
The original string does not change
A method returns a new string and leaves the one it was called on as it was. If you want the converted text, store the result: shout = name.upper(). Calling name.upper() on a line by itself computes the capitals and throws them away, which is the most common mistake with these methods.
1name = "ada"2shout = name.upper()3print(name)4print(shout)
upper() builds shout as a new string; name is read and left as it was.
After the second line runs, name still prints ada and shout prints ADA. To change what name holds, assign back to it: name = name.upper(), the same shape as growing a string with +.
Comparing without caring about case
Text typed by people arrives in whatever case they felt like: Yes, yes, YES. Comparing with == would need a branch per spelling. Lowercasing both sides first collapses them to one spelling, so a single comparison handles them all. The function below returns a boolean, so an if statement can use it directly.
Matching keys from 2 systems
The same trick joins records whose keys were typed by different teams. A warehouse table might store OSLO while a partner's export says Oslo. Lowering both before the comparison, or upper-casing both, makes the match succeed without changing either source.
Letters only
Only letters have case, so the methods pass every other character through unchanged. title() decides where a word starts by looking for a character that isn't a letter, which gives a surprise on text like 3rd street: the r after the digit is treated as the start of a word and gets capitalized.
- ▸The result of a method is a string, so another method can follow it on the same line
- ▸"hELLO".lower().capitalize() gives "Hello"
- ▸Read a chain left to right: each call runs on the previous call's result
What does this program print?
Keeping the converted value
To keep a conversion, put the method call on the right of an =. Assigning to a new name keeps both versions, and assigning back to the same name replaces the old text, which is what you want when the original casing has no further use. The program below calls title() twice: once on a line by itself and once in an assignment.
The first print shows lima because the result of the bare call was discarded. The second shows Lima because city now names the new string. A conversion that appears to do nothing is almost always a call whose result nobody stored.
> Spotify's Wrapped cards show each listener their top artist and minutes listened in a short block of text. A card builder starts from the artist name as typed in the catalog, shows it in capitals, places the minute count on its own line and ends with a tagline that contains a quotation.
Quotes, line breaks, +, backslashes and .upper(): the 5 rules behind every piece of text Python prints.
- Category
- Python
- Difficulty
- beginner
- Duration
- 31 minutes
- Challenges
- 20 hands-on challenges
Topics covered: What is a String?, Multiline Strings, String Concatenation, Escape Characters in Strings, Case Conversion
Lesson Sections
- What is a String? (concepts: Strings)
Text that looks like a number Walking through the characters Equal means every character matches The last line fails for a third reason: the same 4 letters in a different order make a different string. When 2 values that should match come back unequal, compare their case first. If the case matches, look for a stray space or for characters in the wrong order. Each one hides on screen until you compare the strings character by character.
- Multiline Strings (concepts: Type Conversion)
A line break is a character The line break is stored as a single character, so it counts when you walk the string with a loop. The string below shows 4 visible letters on 2 lines, and the loop counts 5. The string starts right after the quotes Indentation inside the quotes is kept Inside a function body your code is indented, and any spaces you type at the start of a continuation line become spaces in the string. The receipt below looks tidy in the source, but the second printed line starts with
- String Concatenation (concepts: Strings)
Growing a string in a loop Repeating with * Only strings join strings A count in a variable sets the repeats
- Escape Characters in Strings (concepts: Strings)
Some characters have no key you can press inside a string. A tab is one. A line break is another when it has to live in a string written with one pair of quotes, and so is a double quote inside a string that is itself delimited by double quotes. The backslash solves this. A backslash followed by 1 character is an escape sequence, and Python stores the character the pair stands for instead of the 2 symbols you typed. An escape sequence is 1 character Triple quotes write \n for you Backslashes in
- Case Conversion (concepts: String Methods)
The original string does not change Comparing without caring about case Matching keys from 2 systems Letters only Keeping the converted value