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
  1. Creating strings
  2. Joining and repeating strings
  3. F-strings: the modern way to build messages
  4. Indexes and slicing
  5. The most useful string methods
  6. Asking the user for data with input()
  7. Full example: a username and email generator
  8. Real case: cleaning an order that came in by text message
  9. Common string mistakes
  10. Summary
What you'll learn
  • 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.

0is the position of the first character of any string in Python, not 1
:,.2fis the format that turns 1459.9 into 1,459.90, like on a real invoice
stris what input() always returns, even when the user types a number

Creating 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.

Use f-strings for everything

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?

  • 1234.5
  • 1,234.50
  • 1,234.5

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.

Indexes of the string TX-2041-B The nine characters T, X, dash, 2, 0, 4, 1, dash and B have positive indexes 0 to 8 and negative indexes -9 to -1. The slice from 3 to 7 takes the characters 2041. code = "TX-2041-B" 012345678 TX-2041-B -9-8-7-6-5-4-3-2-1 code[3:7] → "2041"
  • 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.
Tip: a slice's length is always stop − start. If you're off by one character, check the stop.

2. With text = "Python", what does text[0:3] return?

  • "Pyth"
  • "yth"
  • "Pyt"

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:

MethodWhat it doesExample → 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 textContains 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: "))
What if the user types "twenty"?

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?

  • A TypeError, because input() returns text: you need int(age)
  • It works and adds 1
  • It returns 1

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:

  1. Split.split(";")Breaks the line into four parts: customer, phone, amount and product.
  2. Trim.strip()Removes the spaces at the start and end of each part.
  3. Normalize.title() and .replace()"MIKE o'brien" becomes "Mike O'Brien"; the amount loses its "$" and comma.
  4. Convertfloat()Only once the text is clean can it become a number.
  5. 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)).

  • 3
  • 4
  • 5

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:

  1. Asks for a product name, its price and the quantity (the user might type the price with a "$").
  2. Calculates the total with 7% sales tax (Indiana's statewide rate).
  3. 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, split and join; strings are immutable, so save the result.
  • input() always returns text: convert it with int() or float().
  • Clean before converting: split, strip, replace and only then int() or float().

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.

🎓 Save your progress and get a free certificate

Create your account in 30 seconds, mark your lessons and download your certificate at the end.

Enroll for free