Pythonic Code & Best Practices

Writing Code the Python Way

What is "Pythonic" Code?

You can solve any problem in many ways. But Python has a preferred style — clean, readable, and elegant. Code written this way is called Pythonic.

Two programmers can solve the same problem:


    # Non-Pythonic — works but ugly
    numbers = [1, 2, 3, 4, 5]
    squares = []
    for i in range(len(numbers)):
        squares.append(numbers[i] ** 2)

    # Pythonic — clean and elegant
    squares = [n ** 2 for n in numbers]

Same result. But the second version is shorter, more readable, and more Python-like.

This stage teaches you to write code like an experienced Python developer.


Part 1 — List Comprehensions

The Problem

This pattern appears everywhere:


    # Create a new list by transforming another list
    result = []
    for item in original_list:
        result.append(transform(item))

It works but it's 3 lines every time. List comprehension does it in 1.


Basic List Comprehension


    # Syntax
    new_list = [expression for item in iterable]

Examples:


    # Squares of numbers
    numbers = [1, 2, 3, 4, 5]

    # Old way
    squares = []
    for n in numbers:
        squares.append(n ** 2)

    # List comprehension
    squares = [n ** 2 for n in numbers]
    print(squares)    # [1, 4, 9, 16, 25]

    # Uppercase all strings
    fruits = ["apple", "banana", "mango"]
    upper_fruits = [f.upper() for f in fruits]
    print(upper_fruits)    # ['APPLE', 'BANANA', 'MANGO']

    # Get lengths of words
    words = ["Python", "is", "awesome"]
    lengths = [len(w) for w in words]
    print(lengths)    # [6, 2, 7]


List Comprehension with Condition


    # Syntax
    new_list = [expression for item in iterable if condition]
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    # Only even numbers
    evens = [n for n in numbers if n % 2 == 0]
    print(evens)    # [2, 4, 6, 8, 10]

    # Only numbers greater than 5
    big = [n for n in numbers if n > 5]
    print(big)    # [6, 7, 8, 9, 10]

    # Squares of only even numbers
    even_squares = [n ** 2 for n in numbers if n % 2 == 0]
    print(even_squares)    # [4, 16, 36, 64, 100]


Dictionary Comprehension

Same concept for dictionaries:


    # Syntax
    new_dict = {key: value for item in iterable}

    # Square of each number as dict
    numbers = [1, 2, 3, 4, 5]
    squares_dict = {n: n ** 2 for n in numbers}
    print(squares_dict)    # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

    # Flip keys and values
    original = {"name": "Gagan", "age": 22, "city": "Delhi"}
    flipped = {value: key for key, value in original.items()}
    print(flipped)    # {'Gagan': 'name', 22: 'age', 'Delhi': 'city'}

    # Filter a dictionary
    marks = {"Rahul": 85, "Priya": 92, "Gagan": 45, "Amit": 78, "Neha": 38}
    passed = {name: mark for name, mark in marks.items() if mark >= 50}
    print(passed)    # {'Rahul': 85, 'Priya': 92, 'Amit': 78}


Set Comprehension


    numbers = [1, 2, 2, 3, 3, 3, 4]
    unique_squares = {n ** 2 for n in numbers}
    print(unique_squares)    # {1, 4, 9, 16} — unique values only


When NOT to Use Comprehensions

Comprehensions are great but don't overuse them:


    # Too complex — hard to read
    result = [x ** 2 for x in range(20) if x % 2 == 0 if x % 3 == 0]

    # Better as a regular loop with clear logic
    result = []
    for x in range(20):
        if x % 2 == 0 and x % 3 == 0:
            result.append(x ** 2)

Rule — if comprehension is hard to read in one glance, use a regular loop.


Part 2 — Lambda Functions

What is a Lambda?

A lambda is a small anonymous function — a function without a name, written in one line.


    # Regular function
    def square(n):
        return n ** 2

    # Lambda equivalent
    square = lambda n: n ** 2

    print(square(5))    # 25

Syntax:

lambda parameters: expression

Why Lambda?

Lambdas are not meant to replace regular functions. They're useful when you need a small throwaway function in one place — especially with sorted(), map(), filter().


Lambda with sorted()


    students = [
        {"name": "Rahul", "marks": 85},
        {"name": "Priya", "marks": 92},
        {"name": "Gagan", "marks": 78},
        {"name": "Amit", "marks": 95}
    ]

    # Sort by marks
    sorted_students = sorted(students, key=lambda s: s["marks"])
    for s in sorted_students:
        print(f"{s['name']}: {s['marks']}")

Output:

Gagan: 78
Rahul: 85
Priya: 92
Amit: 95

    # Sort by name
    sorted_by_name = sorted(students, key=lambda s: s["name"])

    # Sort by marks descending
    sorted_desc = sorted(students, key=lambda s: s["marks"], reverse=True)


map() — Apply Function to Every Item


    numbers = [1, 2, 3, 4, 5]

    # Apply function to each item
    squares = list(map(lambda n: n ** 2, numbers))
    print(squares)    # [1, 4, 9, 16, 25]

    # Same as list comprehension
    squares = [n ** 2 for n in numbers]

    # Convert all strings to uppercase
    names = ["rahul", "priya", "gagan"]
    upper = list(map(lambda n: n.upper(), names))
    print(upper)    # ['RAHUL', 'PRIYA', 'GAGAN']


filter() — Filter Items by Condition


    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    # Keep only even numbers
    evens = list(filter(lambda n: n % 2 == 0, numbers))
    print(evens)    # [2, 4, 6, 8, 10]

    # Keep only passing marks
    marks = [85, 42, 90, 38, 75, 55, 29]
    passed = list(filter(lambda m: m >= 50, marks))
    print(passed)    # [85, 90, 75, 55]


Part 3 — Useful Pythonic Patterns

Unpacking


    # Basic unpacking
    a, b, c = [1, 2, 3]
    print(a, b, c)    # 1 2 3

    # Swap variables — Pythonic way
    x, y = 10, 20
    x, y = y, x       # swap in one line
    print(x, y)       # 20 10

    # Extended unpacking
    first, *rest = [1, 2, 3, 4, 5]
    print(first)    # 1
    print(rest)     # [2, 3, 4, 5]

    *beginning, last = [1, 2, 3, 4, 5]
    print(beginning)    # [1, 2, 3, 4]
    print(last)         # 5


Enumerate — Already Seen, Important Enough to Revisit


    fruits = ["apple", "banana", "mango"]

    # Non-Pythonic
    for i in range(len(fruits)):
        print(f"{i + 1}. {fruits[i]}")

    # Pythonic
    for i, fruit in enumerate(fruits, start=1):
        print(f"{i}. {fruit}")

Output:

1. apple
2. banana
3. mango
1. apple
2. banana
3. mango

zip — Combine Two Lists


    names = ["Rahul", "Priya", "Gagan"]
    marks = [85, 92, 78]

    for name, mark in zip(names, marks):
        print(f"{name}: {mark}")

Output:

Rahul: 85
Priya: 92
Gagan: 78

    # Create dictionary from two lists
    students_dict = dict(zip(names, marks))
    print(students_dict)    # {'Rahul': 85, 'Priya': 92, 'Gagan': 78}


any() and all()


    marks = [85, 92, 78, 45, 90]

    # all() — True if ALL items satisfy condition
    all_passed = all(m >= 50 for m in marks)
    print(all_passed)    # False — 45 fails

    # any() — True if AT LEAST ONE item satisfies condition
    anyone_failed = any(m < 50 for m in marks)
    print(anyone_failed)    # True — 45 fails

    # Practical example
    passwords = ["abc", "password123", "xyz"]
    has_strong = any(len(p) >= 8 for p in passwords)
    print(has_strong)    # True — password123 is long enough


Ternary Operator — One Line If/Else


    # Regular if/else
    age = 20
    if age >= 18:
        status = "Adult"
    else:
        status = "Minor"

    # Ternary — one line
    status = "Adult" if age >= 18 else "Minor"
    print(status)    # Adult

    # In f-strings
    age = 20
    print(f"You are {'Adult' if age >= 18 else 'Minor'}")


_ as Throwaway Variable

When you don't need a variable:


    # You need the index but not the value
    for _ in range(5):
        print("Hello")    # print 5 times, don't need loop variable

    # Unpacking but only want some values
    name, _, city = ("Gagan", 22, "Delhi")    # ignore age
    print(name, city)    # Gagan Delhi


Part 4 — Code Quality

Meaningful Names


    # Bad names
    x = 86400
    def calc(a, b):
        return a * b / 100

    # Good names
    SECONDS_IN_DAY = 86400
    def calculate_percentage(score, total):
        return score * total / 100


Constants in UPPER_CASE


    # Constants — values that never change
    MAX_RETRIES = 3
    DEFAULT_TIMEOUT = 30
    DATABASE_URL = "postgresql://localhost/mydb"
    PI = 3.14159


Functions Should Do One Thing


    # Bad — function doing too much
    def process_student(name, marks):
        average = sum(marks) / len(marks)
        if average >= 90: grade = "A"
        elif average >= 80: grade = "B"
        else: grade = "C"
        print(f"Name: {name}")
        print(f"Average: {average}")
        print(f"Grade: {grade}")
        with open("results.txt", "a") as f:
            f.write(f"{name},{average},{grade}\n")

    # Good — each function does one thing
    def calculate_average(marks):
        return sum(marks) / len(marks)

    def get_grade(average):
        if average >= 90: return "A"
        elif average >= 80: return "B"
        else: return "C"

    def print_result(name, average, grade):
        print(f"Name: {name}, Average: {average}, Grade: {grade}")

    def save_result(name, average, grade):
        with open("results.txt", "a") as f:
            f.write(f"{name},{average},{grade}\n")


Docstrings — Document Your Code


    def calculate_average(marks):
        """
        Calculate the average of a list of marks.

        Args:
            marks (list): List of numerical marks

        Returns:
            float: The average mark

        Example:
            >>> calculate_average([85, 90, 78])
            84.33
        """
        if not marks:
            return 0
        return sum(marks) / len(marks)

Docstrings appear when someone calls help(calculate_average). Professional code always has docstrings.


PEP 8 — Python Style Guide

PEP 8 is the official Python style guide. Key rules:


    # Indentation — 4 spaces (not tabs)
    def my_function():
        x = 10
        return x

    # Spaces around operators
    x = 5 + 3        # correct
    x=5+3            # wrong

    # No space before colon in dict/slice
    d = {"key": "value"}     # correct
    d = {"key" : "value"}    # wrong

    # Two blank lines between top-level functions/classes
    def function_one():
        pass


    def function_two():
        pass


    class MyClass:
        pass

    # One blank line between methods inside class
    class MyClass:
        def method_one(self):
            pass

        def method_two(self):
            pass

    # Max line length — 79 characters
    # Long lines — use backslash or parentheses
    result = (value_one + value_two +
            value_three + value_four)

    # Imports — one per line, at the top
    import os
    import json
    from datetime import datetime


Final Real World Example — Everything Together

A clean, Pythonic, well-structured program:


    """
    expense_tracker.py
    A simple expense tracker using Pythonic best practices.
    """

    import json
    import os
    from datetime import datetime

    EXPENSES_FILE = "expenses.json"
    CATEGORIES = ["food", "transport", "shopping", "bills", "entertainment", "other"]


    def load_expenses():
        """Load expenses from JSON file."""
        if not os.path.exists(EXPENSES_FILE):
            return []
        with open(EXPENSES_FILE, "r") as file:
            return json.load(file)


    def save_expenses(expenses):
        """Save expenses to JSON file."""
        with open(EXPENSES_FILE, "w") as file:
            json.dump(expenses, file, indent=4)


    def add_expense(expenses):
        """Add a new expense entry."""
        print("\nCategories:", ", ".join(CATEGORIES))
        description = input("Description: ").strip()
        category = input("Category: ").strip().lower()
       
        if category not in CATEGORIES:
            print(f"Invalid category. Using 'other'")
            category = "other"

        try:
            amount = float(input("Amount (Rs.): "))
            if amount <= 0:
                print("Amount must be positive")
                return
        except ValueError:
            print("Invalid amount")
            return

        expense = {
            "id": len(expenses) + 1,
            "description": description,
            "category": category,
            "amount": amount,
            "date": datetime.now().strftime("%Y-%m-%d")
        }

        expenses.append(expense)
        save_expenses(expenses)
        print(f"Expense added: Rs.{amount:.2f} for {description}")


    def view_expenses(expenses):
        """Display all expenses."""
        if not expenses:
            print("No expenses recorded yet")
            return

        print(f"\n{'ID':<5} {'Date':<12} {'Category':<15} {'Amount':<12} {'Description'}")
        print("-" * 60)

        for e in expenses:
            print(f"{e['id']:<5} {e['date']:<12} {e['category']:<15} Rs.{e['amount']:<10.2f} {e['description']}")

        total = sum(e["amount"] for e in expenses)
        print("-" * 60)
        print(f"{'Total:':<33} Rs.{total:.2f}")


    def view_by_category(expenses):
        """Show expense summary by category."""
        if not expenses:
            print("No expenses recorded yet")
            return

        category_totals = {}
        for e in expenses:
            cat = e["category"]
            category_totals[cat] = category_totals.get(cat, 0) + e["amount"]

        print("\n=== Expenses by Category ===")
        sorted_cats = sorted(category_totals.items(), key=lambda x: x[1], reverse=True)
        for category, total in sorted_cats:
            print(f"  {category:<15}: Rs.{total:.2f}")


    def filter_by_category(expenses):
        """Filter expenses by category."""
        category = input("Enter category: ").strip().lower()
        filtered = [e for e in expenses if e["category"] == category]

        if not filtered:
            print(f"No expenses in category '{category}'")
            return

        print(f"\n=== {category.title()} Expenses ===")
        for e in filtered:
            print(f"  {e['date']} — Rs.{e['amount']:.2f}{e['description']}")

        total = sum(e["amount"] for e in filtered)
        print(f"  Total: Rs.{total:.2f}")


    def main():
        """Main program loop."""
        expenses = load_expenses()
        print(f"Loaded {len(expenses)} existing expenses")

        menu_options = {
            "1": ("Add expense", add_expense),
            "2": ("View all expenses", view_expenses),
            "3": ("View by category", view_by_category),
            "4": ("Filter by category", filter_by_category),
            "5": ("Exit", None)
        }

        while True:
            print("\n=== Expense Tracker ===")
            for key, (label, _) in menu_options.items():
                print(f"{key}. {label}")

            choice = input("Choice: ").strip()

            if choice == "5":
                print("Goodbye!")
                break
            elif choice in menu_options:
                _, func = menu_options[choice]
                func(expenses)
            else:
                print("Invalid choice")


    if __name__ == "__main__":
        main()

Notice what's Pythonic here:

  • Docstrings on every function
  • List comprehension for filtering
  • sum() with generator expression
  • sorted() with lambda
  • Dictionary for menu options
  • .get() for safe dictionary access
  • if __name__ == "__main__" — standard entry point

if __name__ == "__main__" — Explained

def main():
    print("Program running")

if __name__ == "__main__":
    main()

When Python runs a file directly — __name__ equals "__main__" so main() runs. When another file imports this file — __name__ equals the filename so main() does NOT run automatically.

This is standard in every professional Python script. Always write it.


Exercise 🏋️ — Final Project

You've completed all 10 stages. Now build a complete CLI application combining everything:

Personal Finance Manager:

=== Personal Finance Manager ===
1. Add income
2. Add expense  
3. View transactions
4. View balance
5. Monthly summary
6. Export to file
7. Exit

Requirements:

  • OOP — Transaction class, Account class
  • File handling — save/load from JSON
  • Error handling — all inputs validated
  • Modules — datetime, json, os
  • Pythonic code — comprehensions, clean functions, docstrings
  • Categories for both income and expenses
  • Monthly summary showing income vs expense vs savings

This is your capstone project — it combines every single concept from all 10 stages. Take your time, build it properly.


🎉 Congratulations — You've Completed the Roadmap!

Let's look at everything you've learned:

Stage

Topics

Stage 1

Setup, print, variables, data types, math, input

Stage 2

If/else, elif, loops, break, continue

Stage 3

Functions, parameters, return, scope

Stage 4

Lists, tuples, dictionaries, sets

Stage 5

String methods, formatting, f-strings

Stage 6

File read/write, CSV, JSON files

Stage 7

Try/except, error types, raising exceptions

Stage 8

Built-in modules, pip, external libraries

Stage 9

Classes, objects, inheritance, polymorphism

Stage 10

Comprehensions, lambda, Pythonic patterns


What's Next After Core Python?

Now that you know Core Python — pick a direction:

Web Development:

  • Flask or Django framework
  • Build websites and APIs

Data Science / AI:

  • NumPy, Pandas, Matplotlib
  • Machine Learning with scikit-learn

Automation:

  • Selenium — automate browsers
  • PyAutoGUI — automate desktop
  • Schedule — run tasks automatically

Backend Development:

  • FastAPI — modern API framework
  • PostgreSQL with psycopg2
  • REST API development

String Handling in Python

Strings In Depth

Quick Recap

You already know strings from Stage 1:

name = "Gagan"
message = 'Hello World'

But strings in Python are much more powerful than just storing text. Let's go deep.


Strings are Sequences

A string is actually a sequence of characters — just like a list but for text. This means everything you learned about indexing and slicing on lists works on strings too:


    name = "Gagan"
    #       01234

    print(name[0])      # G
    print(name[1])      # a
    print(name[-1])     # n  (last character)
    print(name[1:4])    # aga (slicing)
    print(name[:3])     # Gag
    print(len(name))    # 5  (total characters)


Looping Through a String


    name = "Gagan"

    for char in name:
        print(char)

Output:

G
a
g
a
n

Strings are Immutable

Just like tuples, strings cannot be changed after creation:


    name = "Gagan"
    name[0] = "K"      # ERROR — strings are immutable

But you can create a new string from an old one:


    name = "Gagan"
    new_name = "K" + name[1:]    # 'K' + 'agan'
    print(new_name)               # Kagan


String Methods — The Real Power

Python gives you dozens of built-in methods to work with strings. These are what you'll use every single day in real projects.


Case Methods


    text = "Hello World"

    print(text.upper())       # HELLO WORLD
    print(text.lower())       # hello world
    print(text.title())       # Hello World  (first letter of each word capitalized)
    print(text.capitalize())  # Hello world  (only first letter of string)
    print(text.swapcase())    # hELLO wORLD  (swap upper/lower)

Real use case — case-insensitive comparison:


    username = input("Enter username: ")

    if username.lower() == "gagan":
        print("Welcome!")

Now it works whether user types "Gagan", "GAGAN", "gAgAn" — anything.


Whitespace Methods


    text = "   Hello World   "

    print(text.strip())       # "Hello World"   (removes both sides)
    print(text.lstrip())      # "Hello World   " (removes left side)
    print(text.rstrip())      # "   Hello World" (removes right side)

Real use case — user input always has accidental spaces:


    email = input("Enter email: ")
    email = email.strip().lower()    # clean the input before using it

Always strip and lowercase user input before processing. This is standard practice.


Search Methods


    text = "I love Python programming"

    print(text.find("Python"))        # 7  — index where it starts
    print(text.find("Java"))          # -1 — not found, returns -1
    print(text.count("o"))            # 3  — how many times 'o' appears
    print(text.startswith("I love"))  # True
    print(text.endswith("ing"))       # True
    print("Python" in text)           # True — simplest way to check


Replace Method


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

    new_text = text.replace("Java", "Python")
    print(new_text)    # I love Python. Python is great.

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

Original string is never changed — a new string is returned.


Split and Join — Very Important

split() — breaks a string into a list:


    sentence = "I love Python programming"
    words = sentence.split()         # split by space (default)
    print(words)                     # ['I', 'love', 'Python', 'programming']
    print(words[2])                  # Python

    # Split by custom separator
    csv_data = "Gagan,22,Delhi,Python"
    parts = csv_data.split(",")
    print(parts)                     # ['Gagan', '22', 'Delhi', 'Python']
    print(parts[0])                  # Gagan
    print(parts[2])                  # Delhi

join() — opposite of split, combines a list into a string:


    words = ["I", "love", "Python"]
    sentence = " ".join(words)       # join with space
    print(sentence)                  # I love Python

    tags = ["python", "coding", "beginner"]
    result = ", ".join(tags)         # join with comma and space
    print(result)                    # python, coding, beginner

    path = ["home", "user", "documents"]
    file_path = "/".join(path)
    print(file_path)                 # home/user/documents


Check Methods


    print("hello".isalpha())      # True  — only letters
    print("hello123".isalpha())   # False — has numbers
    print("12345".isdigit())      # True  — only digits
    print("hello123".isalnum())   # True  — letters and numbers
    print("   ".isspace())        # True  — only whitespace
    print("Hello World".istitle()) # True — title case

Real use case — validating user input:


    age = input("Enter your age: ")

    if age.isdigit():
        age = int(age)
        print(f"Your age is {age}")
    else:
        print("Invalid input — please enter a number")


String Formatting — All Three Ways

You've been using f-strings. Let's see all three ways Python supports:

Way 1 — f-strings (Modern, Recommended)


    name = "Gagan"
    age = 22
    print(f"My name is {name} and I am {age} years old")

You can even put expressions directly inside:


    price = 100
    quantity = 3
    print(f"Total: Rs.{price * quantity}")       # Rs.300
    print(f"Pi is approximately {22/7:.4f}")     # Pi is approximately 3.1429


Way 2 — .format() method (Older)


    name = "Gagan"
    age = 22
    print("My name is {} and I am {} years old".format(name, age))

You'll see this in older code. f-strings are better but good to recognize this.


Way 3 — % operator (Very Old)


    name = "Gagan"
    age = 22
    print("My name is %s and I am %d years old" % (name, age))

Very old style — you'll rarely use this. Just recognize it if you see it.

Stick to f-strings — they're the cleanest and most modern.


f-string Formatting Options

You can control how values are displayed inside f-strings:


    number = 1234567.89

    print(f"{number:.2f}")          # 1234567.89  (2 decimal places)
    print(f"{number:,.2f}")         # 1,234,567.89 (comma separator)
    print(f"{number:.0f}")          # 1234568     (no decimals, rounded)

    # Padding and alignment
    name = "Gagan"
    print(f"{name:10}")             # "Gagan     " (10 chars, left aligned)
    print(f"{name:>10}")            # "     Gagan" (10 chars, right aligned)
    print(f"{name:^10}")            # "  Gagan   " (10 chars, center aligned)

    # Numbers with padding
    for i in range(1, 6):
        print(f"Item {i:02d}")      # Item 01, Item 02... (pad with zeros)

Output of last loop:

Item 01
Item 02
Item 03
Item 04
Item 05

Multiline Strings

Use triple quotes for strings that span multiple lines:


    message = """
    Hello Gagan,

    Welcome to our platform.
    Your account has been created successfully.

    Thank you,
    Team Python
    """

    print(message)

Output:


Hello Gagan,

Welcome to our platform.
Your account has been created successfully.

Thank you,
Team Python


Escape Characters

Special characters inside strings:


    print("Hello\nWorld")         # \n = new line
    print("Hello\tWorld")         # \t = tab space
    print("He said \"Hello\"")    # \" = double quote inside string
    print("C:\\Users\\Gagan")     # \\ = backslash

Output:

Hello
World
Hello	World
He said "Hello"
C:\Users\Gagan

Real World Example — User Registration Validator


    def validate_username(username):
        username = username.strip()
        if len(username) < 3:
            return False, "Username too short (minimum 3 characters)"
        if len(username) > 20:
            return False, "Username too long (maximum 20 characters)"
        if not username.isalnum():
            return False, "Username can only contain letters and numbers"
        return True, "Username is valid"

    def validate_email(email):
        email = email.strip().lower()
        if "@" not in email:
            return False, "Email must contain @"
        if "." not in email:
            return False, "Email must contain a dot"
        return True, "Email is valid"

    def validate_password(password):
        if len(password) < 8:
            return False, "Password too short (minimum 8 characters)"
        if password.isalpha():
            return False, "Password must contain at least one number"
        if password.isdigit():
            return False, "Password must contain at least one letter"
        return True, "Password is valid"


    print("=== User Registration ===")

    username = input("Enter username: ")
    email = input("Enter email: ")
    password = input("Enter password: ")

    valid_u, msg_u = validate_username(username)
    valid_e, msg_e = validate_email(email)
    valid_p, msg_p = validate_password(password)

    print(f"\nUsername: {msg_u}")
    print(f"Email: {msg_e}")
    print(f"Password: {msg_p}")

    if valid_u and valid_e and valid_p:
        print("\nRegistration successful!")
    else:
        print("\nRegistration failed. Please fix the errors above.")

This is close to real production code — input validation is something every developer writes.


Quick Reference — All String Methods


    text = "  Hello World  "

    # Case
    text.upper()            # HELLO WORLD
    text.lower()            # hello world
    text.title()            # Hello World
    text.capitalize()       # Hello world

    # Whitespace
    text.strip()            # "Hello World"
    text.lstrip()           # "Hello World  "
    text.rstrip()           # "  Hello World"

    # Search
    text.find("World")      # index or -1
    text.count("l")         # count occurrences
    text.startswith("  H")  # True/False
    text.endswith("  ")     # True/False
    "Hello" in text         # True/False

    # Modify
    text.replace("World", "Python")
    text.split()            # split into list
    " ".join(list)          # join list into string

    # Check
    text.isalpha()          # only letters?
    text.isdigit()          # only digits?
    text.isalnum()          # letters and numbers?
    text.isspace()          # only whitespace?

    # Length
    len(text)               # total characters


Exercise 🏋️

Build a Text Analyzer program:

  1. Ask user to enter any sentence
  2. Analyze and display:
Enter a sentence: Hello World this is Python programming

=== Text Analysis ===
Original text    : Hello World this is Python programming
Uppercase        : HELLO WORLD THIS IS PYTHON PROGRAMMING
Lowercase        : hello world this is python programming
Total characters : 38
Without spaces   : 32
Total words      : 6
Word list        : ['Hello', 'World', 'this', 'is', 'Python', 'programming']
Starts with 'H'  : True
Ends with 'ing'  : True
Contains 'Python': True
Count of 'o'     : 3
Reversed text    : gnimmargorp nohtyP si siht dlroW olleH

Hints:

  • Count without spaces: text.replace(" ", "")
  • Total words: len(text.split())
  • Reversed text: text[::-1] (slicing with step -1 reverses anything)

Phase 3 — Components Deep Dive

Chapter 1 — What We Are Going to Learn and Why In Phase 2 you learned what a component is and how to create one. You know that a component h...