Follow AiTechWorlds on LinkedIn for professional AI content!Follow Now →
20 minLesson 3 of 34
Python Foundations

Strings: The Complete Guide

Strings: The Complete Guide

Strings are everywhere in Python — user input, file contents, API responses, web pages. Mastering them is not optional. This lesson covers every string technique you'll actually use, from basic creation to advanced formatting.

Creating Strings

Python gives you three ways to create strings, each with a purpose:

# Single and double quotes — interchangeable
name = 'Alice'
greeting = "Hello, World!"

# Use the other quote type to avoid escaping
message = "It's a great day"    # single quote inside double quotes
html = 'He said "Python rocks"' # double quotes inside single quotes

# Triple quotes — for multiline text
bio = """My name is Alice.
I love Python.
I write code every day."""

print(bio)
# My name is Alice.
# I love Python.
# I write code every day.

String Indexing and Slicing

Strings are sequences. Every character has a position (index) starting at 0. Python also supports negative indexing from the end:

word = "Python"
#       P y t h o n
# index: 0 1 2 3 4 5
# neg:  -6-5-4-3-2-1

print(word[0])   # P
print(word[1])   # y
print(word[-1])  # n  (last character)
print(word[-2])  # o  (second to last)

Slicing extracts a portion of the string using [start:stop:step]:

text = "Hello, Python!"

print(text[0:5])    # Hello    (index 0 up to but not including 5)
print(text[7:])     # Python!  (from index 7 to end)
print(text[:5])     # Hello    (from start to index 5)
print(text[-7:])    # Python!  (last 7 characters)
print(text[::2])    # Hlo yhn  (every other character)
print(text[::-1])   # !nohtyP ,olleH  (reversed!)

Slicing never raises an IndexError — if the indices are out of range, Python just returns what's available.

String Immutability

This is crucial: strings cannot be changed after creation. They are immutable.

word = "hello"

# This raises a TypeError
# word[0] = "H"  # TypeError: 'str' object does not support item assignment

# Instead, create a new string
word = "H" + word[1:]
print(word)  # Hello

Every string method returns a new string. The original is never modified.

Essential String Methods

Python's string methods are all you need for 95% of text processing tasks.

Case Methods

text = "  Hello, Python!  "

print(text.upper())      # "  HELLO, PYTHON!  "
print(text.lower())      # "  hello, python!  "
print(text.title())      # "  Hello, Python!  "
print(text.capitalize()) # "  hello, python!  " (only first char of whole string)
print(text.swapcase())   # "  hELLO, pYTHON!  "

Stripping Whitespace

text = "   hello world   "

print(text.strip())    # "hello world"  — removes both ends
print(text.lstrip())   # "hello world   " — removes left only
print(text.rstrip())   # "   hello world" — removes right only

# Strip specific characters
filename = "###report.csv###"
print(filename.strip("#"))  # "report.csv"

Splitting and Joining

split() and join() are workhorses for parsing and building text:

# split() — break string into a list
sentence = "the quick brown fox"
words = sentence.split()          # splits on whitespace by default
print(words)  # ['the', 'quick', 'brown', 'fox']

csv_line = "Alice,30,Engineer"
parts = csv_line.split(",")
print(parts)  # ['Alice', '30', 'Engineer']

# split with maxsplit
data = "one:two:three:four"
print(data.split(":", 2))  # ['one', 'two', 'three:four']

# join() — combine a list into a string
words = ['Python', 'is', 'great']
sentence = " ".join(words)
print(sentence)  # Python is great

# Join with different separators
print(", ".join(["apple", "banana", "cherry"]))  # apple, banana, cherry
print("-".join("ABC"))  # A-B-C

Searching Within Strings

text = "The quick brown fox jumps over the lazy dog"

# find() — returns index, or -1 if not found
print(text.find("fox"))    # 16
print(text.find("cat"))    # -1

# index() — like find(), but raises ValueError if not found
print(text.index("fox"))   # 16

# count() — how many times does a substring appear?
print(text.count("the"))   # 1 (case-sensitive)
print(text.lower().count("the"))  # 2

# startswith() and endswith()
url = "https://python.org"
print(url.startswith("https"))  # True
print(url.endswith(".org"))      # True
print(url.startswith(("http", "ftp")))  # True — accepts a tuple!

Replacing Text

sentence = "I love Java. Java is great."

new_sentence = sentence.replace("Java", "Python")
print(new_sentence)  # I love Python. Python is great.

# Replace only the first occurrence
partial = sentence.replace("Java", "Python", 1)
print(partial)  # I love Python. Java is great.

Checking String Content

print("hello".isalpha())     # True  — all letters
print("hello123".isalpha())  # False — contains digits
print("123".isdigit())       # True  — all digits
print("abc123".isalnum())    # True  — letters or digits
print("  ".isspace())        # True  — all whitespace
print("Hello World".istitle()) # True — title case

The in Operator — Substring Membership

text = "Python is amazing"

print("Python" in text)         # True
print("python" in text)         # False — case-sensitive
print("python" in text.lower()) # True
print("Java" not in text)       # True

# Extremely useful in conditionals
email = "user@example.com"
if "@" in email and "." in email:
    print("Looks like a valid email")  # Looks like a valid email

f-Strings: The Full Power

f-strings (available since Python 3.6) are the modern standard for string formatting:

name = "Alice"
age = 30
score = 95.678

# Basic variable embedding
print(f"Name: {name}, Age: {age}")  # Name: Alice, Age: 30

# Expressions — any valid Python expression works inside braces
print(f"In 5 years: {age + 5}")          # In 5 years: 35
print(f"Upper: {name.upper()}")          # Upper: ALICE
print(f"Initials: {name[0]}.")           # Initials: A.

# Number formatting
print(f"Score: {score:.1f}")             # Score: 95.7  (1 decimal)
print(f"Score: {score:.2f}")             # Score: 95.68 (2 decimals)
print(f"Big: {1234567:,}")               # Big: 1,234,567 (comma separator)
print(f"Percent: {0.875:.1%}")           # Percent: 87.5%
print(f"Hex: {255:#x}")                  # Hex: 0xff

# Width and alignment
print(f"{'Left':<10}|{'Center':^10}|{'Right':>10}")
# Left      |  Center  |     Right

# Debugging with = (Python 3.8+)
x = 42
print(f"{x = }")    # x = 42  — shows name AND value

Raw Strings

Prefix with r to treat backslashes as literal characters. Essential for file paths and regex:

# Without raw string — \n is a newline, \t is a tab
path = "C:\new_folder\table.csv"
print(path)
# C:
# ew_folder	able.csv  — oops!

# With raw string — backslashes are literal
path = r"C:\new_folder\table.csv"
print(path)  # C:\new_folder\table.csv

# Also useful for regex patterns
import re
pattern = r"\d+\.\d+"  # matches decimal numbers like 3.14
matches = re.findall(pattern, "pi is 3.14 and e is 2.71")
print(matches)  # ['3.14', '2.71']

String Comparison

Strings compare lexicographically (character by character using Unicode values):

print("apple" == "apple")  # True
print("apple" == "Apple")  # False — case-sensitive
print("apple" < "banana")  # True  — 'a' comes before 'b'
print("b" > "a")           # True
print("Z" < "a")           # True  — uppercase letters come before lowercase in Unicode

# Case-insensitive comparison
s1 = "Hello"
s2 = "hello"
print(s1.lower() == s2.lower())  # True

Multiline Strings in Practice

# HTML template
html_template = """
<!DOCTYPE html>
<html>
  <head><title>{title}</title></head>
  <body><h1>{heading}</h1></body>
</html>
""".strip()

# SQL query stored cleanly
query = """
    SELECT name, email
    FROM users
    WHERE active = 1
    ORDER BY name
""".strip()

print(query)
# SELECT name, email
# FROM users
# WHERE active = 1
# ORDER BY name

Practical Exercises

Exercise 1: Username normalizer

def normalize_username(raw_input):
    """Clean and normalize a username."""
    cleaned = raw_input.strip()           # remove leading/trailing spaces
    cleaned = cleaned.lower()             # lowercase
    cleaned = cleaned.replace(" ", "_")   # replace spaces with underscores
    return cleaned

print(normalize_username("  Alice Smith  "))  # alice_smith
print(normalize_username("BOB JONES"))        # bob_jones

Exercise 2: Simple CSV parser

def parse_csv_line(line):
    """Parse a CSV line into a dictionary."""
    fields = line.strip().split(",")
    return {
        "name":  fields[0],
        "age":   int(fields[1]),
        "city":  fields[2]
    }

record = parse_csv_line("Alice,30,New York")
print(record)  # {'name': 'Alice', 'age': 30, 'city': 'New York'}
print(f"{record['name']} is {record['age']} years old, lives in {record['city']}.")
# Alice is 30 years old, lives in New York.

Exercise 3: Password validator

def validate_password(password):
    errors = []
    if len(password) < 8:
        errors.append("at least 8 characters required")
    if not any(c.isupper() for c in password):
        errors.append("must contain an uppercase letter")
    if not any(c.isdigit() for c in password):
        errors.append("must contain a digit")
    return errors

issues = validate_password("hello")
if issues:
    print("Password issues: " + ", ".join(issues))
# Password issues: at least 8 characters required, must contain an uppercase letter, must contain a digit

issues = validate_password("SecurePass1")
print(issues)  # []  — no issues!

What's Next

You now have a complete toolkit for working with text in Python. In the next lesson, we tackle control flow — teaching Python to make decisions using if, elif, and else, including Python 3.10's powerful new match/case statement.

📱

Get this course's notes on Telegram!

Free cheat sheets, summaries & practice exercises

Get Notes Free →
!