Lesson 3 of 16 · Level 1: Beginner
Python Strings, F-Strings and input()
- ⏱ 12 min read
- ❓ 4 review questions
- ✍️ Exercise with solution
In this lesson
- Creating strings
- Joining and repeating strings
- F-strings: the modern way to build messages
- Indexes and slicing
- The most useful string methods
- Asking the user for data with input()
- Full example: a username and email generator
- Real case: cleaning an order that came in by text message
- Common string mistakes
- Summary
- Create, join and cut strings with indexes and slicing.
- Build messages with f-strings and format numbers as dollars and percentages.
- Use the string methods you'll need every day.
- Ask the user for data with input() and convert it.
- Clean messy customer data: extra spaces, mixed capitals, dollar signs and comma separators.
Almost every program works with text: customer names, emails, messages, product codes, addresses. In Python, text is called a string (str). In this lesson you'll learn to slice and clean strings, build readable messages with f-strings, and ask users for data with input() so your programs become interactive.
1459.9 into 1,459.90, like on a real invoiceinput() always returns, even when the user types a numberCreating strings
greeting = "Hello"
city = 'Seattle'
quote = "She said: 'see you tomorrow'" # single quotes inside double quotes
paragraph = """This text
spans several
lines."""
Single and double quotes work the same way; pick one style and stay consistent. Triple quotes let a string span several lines. For special characters you use a backslash: \n is a new line and \t is a tab.
print("Product:\tCoffee\nPrice:\t\t12.50")
Product: Coffee
Price: 12.50
Joining and repeating strings
first = "Jane"
last = "Doe"
full = first + " " + last # "Jane Doe"
print("-" * 20) # a line of 20 dashes
To join a string with a number you have to convert the number first: "Age: " + str(30). Otherwise you get the TypeError you met in lesson 2. Luckily, there's a much better way.
F-strings: the modern way to build messages
Put an f before the opening quote and write variables inside curly braces:
product = "Keyboard"
price = 25.5
quantity = 3
print(f"{quantity} x {product} = {price * quantity}")
# 3 x Keyboard = 76.5
You can put any expression inside the braces, and you can format numbers after a colon:
total = 1234567.891
print(f"Total: {total:,.2f}") # Total: 1,234,567.89 (comma separators, 2 decimals)
print(f"Progress: {0.875:.1%}") # Progress: 87.5%
print(f"Code: {42:05d}") # Code: 00042 (padded with zeros)
Read :,.2f as three instructions: , adds thousands separators, .2 means two decimal places and f means "fixed-point number." Put a dollar sign in front of the braces and you have money formatting: f"${total:,.2f}" prints $1,234,567.89.
They're easier to read and faster than joining with + or using .format(). They've worked since Python 3.6, so any current installation supports them.
1. With price = 1234.5, what does f"{price:,.2f}" return?
The comma adds a thousands separator and .2f shows exactly two decimals, so you get 1,234.50.
Indexes and slicing
Every character in a string has a position, starting at 0. Negative indexes count from the end. Take a product SKU from a warehouse in Texas:
code = "TX-2041-B"
print(code[0]) # T
print(code[-1]) # B (the last one)
print(code[0:2]) # TX (from 0 up to 2, not including 2)
print(code[3:7]) # 2041
print(code[:2]) # TX (from the start)
print(code[3:]) # 2041-B (to the end)
print(len(code)) # 9 (number of characters)
The rule to remember for a slice [start:stop]: it includes the start and excludes the stop. So [0:2] is 2 characters.
- Positive indexes 0 to 8Count from the start:
code[0]is "T". - Negative indexes −9 to −1Count from the end:
code[-1]is "B". - Slice [3:7] "2041"Includes position 3 and stops before 7: 7 − 3 = 4 characters.
2. With text = "Python", what does text[0:3] return?
Indexes start at 0 and the slice [start:stop] excludes the stop: positions 0, 1 and 2.
The most useful string methods
Methods are functions you call on a value with a dot. Strings have dozens; these are the ones you'll use constantly:
| Method | What it does | Example → result |
|---|---|---|
.upper() / .lower() | Uppercase / lowercase | "austin".upper() → "AUSTIN" |
.title() | Capitalizes each word | "jane doe".title() → "Jane Doe" |
.strip() | Removes spaces at both ends | " hello ".strip() → "hello" |
.replace(a, b) | Replaces text | "$1,250".replace(",", "") → "$1250" |
.split(sep) | Splits into a list | "a,b,c".split(",") → ['a', 'b', 'c'] |
sep.join(list) | Joins a list into a string | ", ".join(["a","b"]) → "a, b" |
.startswith() / .endswith() | Starts / ends with…? | "photo.jpg".endswith(".jpg") → True |
.find(x) | Position of x (−1 if missing) | "hello".find("l") → 2 |
.count(x) | How many times x appears | "banana".count("a") → 3 |
x in text | Contains x? | "@" in "jane@mail.com" → True |
Important: strings are immutable. Methods don't change the original string; they return a new one. That's why you have to store the result: name = name.strip().title(). You can chain methods like that because each one returns a string the next one can work on.
Asking the user for data with input()
input() shows a prompt, waits for the user to type something and press Enter, and returns what they typed always as a string:
name = input("What's your name? ")
print(f"Nice to meet you, {name.strip().title()}")
If you need a number, convert it:
age = int(input("How old are you? "))
print(f"Next year you'll be {age + 1}")
price = float(input("Price: "))
int("twenty") raises a ValueError and the program stops. In lesson 8 you'll handle it with try/except; for now, assume the user types something valid. Also remember that float() chokes on dollar signs and commas, which people type all the time. Clean first: float(text.replace("$", "").replace(",", "")).
3. You write age = input("Age: ") and then age + 1. What happens?
input() always returns a str, even if the person types digits. Convert it with int() before doing math.
Full example: a username and email generator
first = input("First name: ").strip().lower()
last = input("Last name: ").strip().lower()
year = input("Birth year: ").strip()
username = f"{first[0]}{last}{year[-2:]}"
email = f"{first}.{last}@company.com"
print(f"Username: {username}")
print(f"Email: {email}")
With "Jane", "Doe" and "1996," the program prints jdoe96 and jane.doe@company.com. Notice how first[0] takes the first initial and year[-2:] takes the last two digits, whatever the length of the input.
Real case: cleaning an order that came in by text message
Real data almost never arrives clean. A hardware store in Columbus, Ohio, takes orders by text message, and someone pastes each one into a single line with extra spaces, random capitals, and the amount typed with a dollar sign and a comma. Before you save or add anything, you have to clean it. Here's the path each piece of data follows:
- Split
.split(";")Breaks the line into four parts: customer, phone, amount and product. - Trim
.strip()Removes the spaces at the start and end of each part. - Normalize
.title()and.replace()"MIKE o'brien" becomes "Mike O'Brien"; the amount loses its "$" and comma. - Convert
float()Only once the text is clean can it become a number. - PresentFormatted f-stringEverything prints neatly, with a U.S. phone format and dollar amounts.
# Text-message order at a hardware store in Columbus, Ohio
line = " MIKE o'brien ; 614 555 0142 ; $ 1,459.90 ; deck screws 3in "
parts = line.split(";")
customer = parts[0].strip().title()
phone = parts[1].replace(" ", "")
amount = float(parts[2].replace("$", "").replace(",", "").strip())
product = parts[3].strip()
deposit = amount / 2
print(f"Customer: {customer}")
print(f"Phone: ({phone[:3]}) {phone[3:6]}-{phone[6:]}")
print(f"Product: {product}")
print(f"Amount: ${amount:,.2f}")
print(f"Deposit: ${deposit:,.2f}")
Output:
Customer: Mike O'Brien
Phone: (614) 555-0142
Product: deck screws 3in
Amount: $1,459.90
Deposit: $729.95
The {amount:,.2f} format uses the U.S. style out of the box: commas for thousands and a dot for cents. If you ever send an invoice to a client in Germany or Brazil, where they write 1.234,50, you can swap the two symbols with a placeholder step: f"{1234.5:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".") gives 1.234,50.
The classic error: IndexError
In the username generator above, if the person presses Enter without typing a first name, first is empty and first[0] fails:
Traceback (most recent call last):
File "username.py", line 5, in <module>
username = f"{first[0]}{last}{year[-2:]}"
~~~~~^^^
IndexError: string index out of range
"Index out of range" means you asked for position 0 of a string that has no characters at all. Slices, on the other hand, never fail: ""[0:1] returns an empty string. In lesson 4 you'll learn to check with an if that the input isn't empty before using it.
4. What does this code print? name = " sam ", then name.strip(), then print(len(name)).
Strings are immutable: name.strip() returns a new string, but since it wasn't saved, name still has its 5 characters (space, s, a, m, space). The fix is name = name.strip().
Common string mistakes
Forgetting the f: print("Total: {total}").
Without the f, Python prints the braces literally. There's no error, which is why it's easy to miss: write f"Total: {total}".
Calling .upper() or .strip() without saving the result.
Reassign: city = city.strip().upper().
Comparing strings without normalizing: "Austin" == "austin" is False.
Compare lowercase, trimmed values: city.strip().lower() == "austin".
Converting amounts with symbols: float("$ 1,459.90").
Remove the dollar sign and the commas with .replace() first, then convert.
Using text[0] without knowing whether the text has content.
Check that it isn't empty first, or use a slice (text[:1]), which never fails.
Good habits with strings
- Clean at the input, once:
city = input("City: ").strip().title(). The rest of the program then works with tidy data. - Store amounts as numbers and format them only when displaying. If you store
"$1,459.90"as text, you can't add it up later. - Use f-strings for any message with variables; save
+for joining two simple strings. - Keep formatting in one place: if all your amounts use
:,.2f, changing the look of a report takes minutes.
Practice exercise
Write a program that:
- Asks for a product name, its price and the quantity (the user might type the price with a "$").
- Calculates the total with 7% sales tax (Indiana's statewide rate).
- Prints a receipt in this format, with two decimals and dollar signs:
------------------------------
Product: Wireless mouse
Quantity: 2
Subtotal: $50.00
Sales tax: $3.50
TOTAL: $53.50
------------------------------
See solution
product = input("Product: ").strip()
price = float(input("Price: ").replace("$", "").replace(",", ""))
quantity = int(input("Quantity: "))
subtotal = price * quantity
tax = subtotal * 0.07
total = subtotal + tax
print("-" * 30)
print(f"Product: {product}")
print(f"Quantity: {quantity}")
print(f"Subtotal: ${subtotal:,.2f}")
print(f"Sales tax: ${tax:,.2f}")
print(f"TOTAL: ${total:,.2f}")
print("-" * 30)
Typing "Wireless mouse," "$25.00" and "2" produces exactly the receipt above: $25.00 × 2 = $50.00, and 7% of that is $3.50.
Summary
- Strings go in quotes; indexes start at 0 and
[start:stop]excludes the stop. - F-strings (
f"${amount:,.2f}") are the best way to build text and format money. - Key methods:
strip,lower,title,replace,splitandjoin; strings are immutable, so save the result. input()always returns text: convert it withint()orfloat().- Clean before converting:
split,strip,replaceand only thenint()orfloat().
Next lesson: Python Conditionals: if, elif, else and match. You'll make your programs take decisions with compound conditions, truthy and falsy values, the ternary expression and match.
Create your account in 30 seconds, mark your lessons and download your certificate at the end.