Chapter 7 Exercises: Understanding AI-Generated Code


Tier 1: Recall (Exercises 1-6)

Exercise 1: Structural Elements List the four structural layers of a Python file that you should identify during a structural analysis scan. For each layer, give one example of what you would look for.

Exercise 2: Complexity Classification Match each operation with its algorithmic complexity:

Operation Complexity
A. Looking up a key in a dictionary 1. O(n^2)
B. Sorting a list 2. O(1)
C. Scanning every item in a list 3. O(n)
D. Nested loop over the same list 4. O(n log n)

Exercise 3: AI Code Patterns Name five common patterns found in AI-generated code that were discussed in section 7.5. For each, write one sentence explaining why it is problematic.

Exercise 4: Security Red Flags List at least five security issues to check for when reviewing AI-generated code. Which one do you think is most commonly introduced by AI code generators?

Exercise 5: Import Categories Classify each of the following imports as standard library, third-party, or local:

import json
from flask import Flask
import os
from .models import User
import requests
from datetime import datetime
from pathlib import Path
import pandas as pd
from utils import helper

Exercise 6: Review Phases Name the five phases of the code review process described in section 7.10, and state the approximate time each phase should take.


Tier 2: Apply (Exercises 7-12)

Exercise 7: Tracing Practice Trace through the following function with the input items = [3, 1, 4, 1, 5, 9, 2, 6]. Write out the value of each variable after each line executes, and state the return value.

def mystery(items: list[int]) -> list[int]:
    result = []
    seen = set()
    for item in items:
        if item not in seen:
            result.append(item)
            seen.add(item)
    return result

Exercise 8: Name Improvement Rewrite the following function with improved naming. Do not change the logic, only the names of the function, parameters, and variables:

def proc(d, k, v=None):
    r = {}
    for i in d:
        if i.get(k) == v or v is None:
            r[i["id"]] = i
    return r

Exercise 9: Edge Case Identification For the following function, list at least four edge cases that could cause problems. For each, state what would happen:

def average(numbers: list[float]) -> float:
    total = sum(numbers)
    return total / len(numbers)

Exercise 10: Unused Import Detection Examine the following code and identify all unused imports:

import json
import os
import sys
import re
from datetime import datetime, timedelta
from typing import Optional, List, Dict
from pathlib import Path

def get_timestamp() -> str:
    return datetime.now().isoformat()

def load_data(filepath: str) -> dict:
    path = Path(filepath)
    with open(path) as f:
        return json.load(f)

def format_name(first: str, last: str) -> str:
    return f"{first} {last}"

Exercise 11: Fixing Validation The following function has no input validation. Add appropriate validation with clear error messages:

def create_user(username: str, email: str, age: int) -> dict:
    return {
        "username": username,
        "email": email,
        "age": age,
        "created_at": datetime.now().isoformat()
    }

Exercise 12: Performance Fix The following function has a performance issue. Identify the issue, explain why it is problematic, and rewrite the function to fix it:

def find_common_items(list_a: list[str], list_b: list[str]) -> list[str]:
    common = []
    for item in list_a:
        if item in list_b and item not in common:
            common.append(item)
    return common

Tier 3: Analyze (Exercises 13-18)

Exercise 13: Complete Code Review Perform a full five-phase code review on the following AI-generated function. Document your findings for each phase:

def export_tasks(tasks, format="csv", filepath=None):
    # Export tasks to a file
    if format == "csv":
        import csv
        # Open the file
        f = open(filepath, "w")
        writer = csv.writer(f)
        # Write the header
        writer.writerow(["ID", "Title", "Priority", "Status"])
        # Write each task
        for task in tasks:
            writer.writerow([task.id, task.title, task.priority,
                           "Done" if task.completed else "Pending"])
        f.close()
        return True
    elif format == "json":
        import json
        data = []
        for task in tasks:
            data.append({
                "id": task.id,
                "title": task.title,
                "priority": task.priority,
                "completed": task.completed
            })
        if filepath:
            with open(filepath, "w") as f:
                json.dump(data, f)
        return data
    else:
        return False

Exercise 14: Pattern Identification The following code was generated by an AI. Identify at least three AI code patterns from section 7.5 and explain how each could be improved:

def get_active_tasks(tasks: list) -> list:
    """Get active tasks from the list of tasks."""
    # Initialize an empty list to store active tasks
    active_tasks = []
    # Loop through each task in the tasks list
    for task in tasks:
        # Check if the task is not completed
        if task.completed == False:
            # Add the task to the active tasks list
            active_tasks.append(task)
    # Return the list of active tasks
    return active_tasks

def get_completed_tasks(tasks: list) -> list:
    """Get completed tasks from the list of tasks."""
    # Initialize an empty list to store completed tasks
    completed_tasks = []
    # Loop through each task in the tasks list
    for task in tasks:
        # Check if the task is completed
        if task.completed == True:
            # Add the task to the completed tasks list
            completed_tasks.append(task)
    # Return the list of completed tasks
    return completed_tasks

def get_high_priority_tasks(tasks: list) -> list:
    """Get high priority tasks from the list of tasks."""
    # Initialize an empty list to store high priority tasks
    high_priority_tasks = []
    # Loop through each task in the tasks list
    for task in tasks:
        # Check if the task is high priority
        if task.priority == "high":
            # Add the task to the high priority tasks list
            high_priority_tasks.append(task)
    # Return the list of high priority tasks
    return high_priority_tasks

Exercise 15: Security Audit Review the following AI-generated web route for security issues. List every vulnerability you find and explain how to fix each one:

from flask import Flask, request, render_template_string
import sqlite3
import os

app = Flask(__name__)
DATABASE = "users.db"
SECRET = "flask-secret-key-2025"

@app.route("/search")
def search():
    query = request.args.get("q", "")
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()
    results = cursor.execute(
        f"SELECT * FROM users WHERE name LIKE '%{query}%'"
    ).fetchall()
    conn.close()
    return render_template_string(
        "<h1>Results for: {{ query }}</h1>"
        "<ul>{% for r in results %}<li>{{ r[1] }}</li>{% endfor %}</ul>",
        query=query, results=results
    )

@app.route("/profile/<username>")
def profile(username):
    photo_path = f"static/photos/{username}.jpg"
    if os.path.exists(photo_path):
        return f"<img src='/{photo_path}'>"
    return "<p>No photo</p>"

Exercise 16: Dependency Analysis You receive AI-generated code with the following imports. Research each third-party package and answer the questions below:

import requests
from bs4 import BeautifulSoup
import lxml
from fake_useragent import UserAgent
import tqdm
from retry import retry

Questions: 1. What does each package do? 2. Which packages are essential vs. optional for a web scraper? 3. What are the approximate install sizes? 4. Are there standard library alternatives for any of these?

Exercise 17: Performance Comparison Two AI-generated implementations of the same function are shown below. Analyze the performance characteristics of each. Which is better for 100 items? For 1,000,000 items? Explain your reasoning.

Implementation A:

def find_task_by_title(tasks: list[Task], title: str) -> Task | None:
    for task in tasks:
        if task.title.lower() == title.lower():
            return task
    return None

Implementation B:

def find_task_by_title(tasks: list[Task], title: str) -> Task | None:
    task_map = {task.title.lower(): task for task in tasks}
    return task_map.get(title.lower())

Exercise 18: Error Handling Audit The following function handles several operations that could fail. Identify every point of failure and add appropriate error handling:

def backup_tasks(source_path: str, backup_dir: str) -> str:
    with open(source_path) as f:
        data = json.load(f)

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_path = Path(backup_dir) / f"tasks_backup_{timestamp}.json"

    with open(backup_path, "w") as f:
        json.dump(data, f, indent=2)

    return str(backup_path)

Tier 4: Create (Exercises 19-24)

Exercise 19: Build a Naming Linter Write a Python function that analyzes a list of function and variable names and flags potential naming issues. It should check for: - Single-character names (except loop variables i, j, k) - Names that are too short (under 3 characters) - Names that use abbreviations instead of full words - CamelCase where snake_case should be used - Names that start with a number (invalid Python)

Exercise 20: Build a Complexity Estimator Write a Python function that takes a string of Python code and provides a rough estimate of its complexity by counting: - Number of nested loops (each level of nesting multiplies complexity) - Number of function calls inside loops - Number of conditional branches

Return a "complexity score" with a simple explanation.

Exercise 21: Build an Import Analyzer Write a Python function that parses a Python source file and produces a report of: - Standard library imports - Third-party imports (not in the standard library) - Local/relative imports - Potentially unused imports (imports whose names do not appear elsewhere in the code)

Exercise 22: Build a Code Review Report Generator Create a system that takes a Python source file and generates a structured code review report with sections for: - Structural overview (counts of classes, functions, imports) - Naming quality assessment - Error handling coverage - Potential issues found - Recommendations for improvement

Exercise 23: Build a Tracing Helper Write a Python decorator called @trace that, when applied to a function, prints the function name, input arguments, and return value every time the function is called. Use this to trace through a multi-function program without manually tracking values.

Exercise 24: Build a Diff Reviewer Write a function that takes two versions of a Python function (as strings) and highlights what changed between them. Categorize each change as: cosmetic (formatting/naming), functional (logic change), safety (error handling added), or performance (optimization).


Tier 5: Challenge (Exercises 25-30)

Exercise 25: AI Output Comparison Use two different AI tools (or the same tool with different prompts) to generate a solution for the following task: "Write a Python function that finds all duplicate files in a directory by comparing their contents." Review both outputs using the full five-phase checklist. Write a comparative analysis of at least 500 words discussing the differences in quality, patterns, and issues.

Exercise 26: The Bug Hunter Challenge The following code has exactly five bugs, ranging from subtle to serious. Find all five, explain each one, and provide the corrected version:

def merge_task_lists(primary: list[dict], secondary: list[dict]) -> list[dict]:
    """Merge two task lists, preferring primary for duplicates."""
    merged = {}

    for task in secondary:
        merged[task["id"]] = task

    for task in primary:
        merged[task["id"]] = task

    result = list(merged.values())
    result.sort(key=lambda t: t["created_at"])

    # Reassign sequential IDs
    for i in range(len(result)):
        result[i]["id"] = i

    # Calculate statistics
    total = len(result)
    completed = len([t for t in result if t["status"] == "done"])
    completion_rate = completed / total

    return {
        "tasks": result,
        "total": total,
        "completed": completed,
        "completion_rate": f"{completion_rate:.1%}",
        "merged_from": [len(primary), len(secondary)]
    }

Exercise 27: Security Hardening Take the task manager code from Chapter 6 and perform a complete security review. Write a report of at least 500 words covering: - All potential security issues found - Risk assessment for each issue (low/medium/high) - Recommended fixes with code examples - Issues that are acceptable given the local CLI context vs. those that would be critical in a web application

Exercise 28: Performance Optimization Project Write a task manager search function that must handle a task list of 1,000,000 entries efficiently. Design and implement: - An index structure for fast lookup by title, priority, and date range - A search function that uses the index instead of scanning all tasks - Benchmarks comparing the indexed search vs. a naive linear scan - A clear analysis of the time/space tradeoffs

Exercise 29: The Meta-Review Write a Python program that reviews AI-generated Python code automatically. Your program should implement at least 10 checks from the code review checklist in section 7.10 and produce a structured report. Test it on at least three different AI-generated code samples and evaluate its effectiveness.

Exercise 30: Teaching Exercise Create a teaching worksheet for someone new to code review. Include: - A piece of AI-generated code with exactly 8 issues of varying severity - A guided walkthrough format where the student answers questions that lead them to discover each issue - A rubric for self-assessment - An answer key with detailed explanations

This exercise is about your ability to understand code review deeply enough to teach it to others.