Home

02 Exercise: PEP 8 - Level 2: Multiple Issues

exercises chapter-02 pep8 code-quality python practice

Introduction

Welcome to Level 2 PEP 8 Exercises! These exercises are designed to help you develop a keen eye for multiple code quality issues simultaneously.

Learning Objectives:

Instructions:

  1. Read each code example carefully
  2. Try to find ALL PEP 8 violations before checking the solution
  3. Write down your answers (recommended for learning)
  4. Click “Show Solution” only after you’ve attempted the exercise
  5. Compare your findings with the provided solution

Difficulty: Intermediate
Time: 5-10 minutes per exercise
Prerequisites: Complete Level 1 exercises first


Exercise 2.1: Data Processing Function

Problem

import sys,os
import numpy as np

def ProcessData(input_list,threshold=10):
    result=[]
    for item in input_list:
        if item>threshold:result.append(item*2)
    return result

Questions

  1. List ALL PEP 8 violations (aim for 5-7 issues)
  2. For each issue, state the violated rule
  3. Write the fully corrected version

Your Turn

Before checking the solution, try to:

💡 Show Solution

Issues Found

  1. Line 1: Multiple imports on one line (sys,os)
    • Rule: Imports should usually be on separate lines
  2. Line 1: Unused imports (sys and os are never used)
    • Rule: Remove unused imports to keep code clean
  3. Line 4: Function name uses PascalCase instead of snake_case (ProcessData)
    • Rule: Function names should be lowercase with words separated by underscores
  4. Line 4: Missing space after comma in parameters (input_list,threshold)
    • Rule: Use spaces after commas in parameter lists
  5. Line 5: Missing spaces around assignment operator (result=[])
    • Rule: Always surround operators with a single space on either side
  6. Line 7: Missing spaces around comparison operator (item>threshold)
    • Rule: Always surround binary operators with spaces
  7. Line 7: Multiple statements on one line (:result.append)
    • Rule: Compound statements (multiple statements on the same line) are generally discouraged

Corrected Version

import numpy as np

def process_data(input_list, threshold=10):
    result = []
    for item in input_list:
        if item > threshold:
            result.append(item * 2)
    return result

Key Takeaways

  • Removing unused imports reduces clutter and startup time
  • PascalCase is for classes, snake_case is for functions
  • Whitespace around operators significantly improves readability
  • One statement per line makes code easier to debug and understand

Exercise 2.2: Road Profile Generator

Problem

from dash import Dash,html,dcc
import numpy as np
import sys

def generate_road_profile(num_points=100,x_max=80):
    x=np.linspace(0,x_max,num_points)
    y=0.015*x**3+0.3*np.sin(2*np.pi*x)
    return x,y

camera_position={'x':0,'y':2.0,'z':1.5}
MAX_distance=100

Questions

  1. List ALL PEP 8 violations (aim for 10-12 issues)
  2. For each issue, state the violated rule
  3. Write the fully corrected version

Hints

💡 Show Solution

Issues Found

  1. Line 1: Multiple imports on one line (Dash,html,dcc)
    • Rule: Imports should be on separate lines
  2. Line 1: Missing spaces after commas in import
    • Rule: Use spaces after commas
  3. Line 3: Unused import (sys)
    • Rule: Remove unused imports
  4. Line 5: Missing space after comma in parameters (num_points=100,x_max=80)
    • Rule: Use spaces after commas
  5. Line 6: Missing spaces around assignment (x=)
    • Rule: Surround operators with spaces
  6. Line 6: Missing spaces after commas (0,x_max,num_points)
    • Rule: Use spaces after commas
  7. Line 7: Missing spaces around assignment (y=)
    • Rule: Surround operators with spaces
  8. Line 7: Missing spaces around multiplication operators (0.015*x, 0.3*np.sin)
    • Rule: Surround binary operators with spaces
  9. Line 7: Missing spaces around addition operator (x**3+0.3)
    • Rule: Surround binary operators with spaces
  10. Line 8: Missing space after comma in return (x,y)
    • Rule: Use spaces after commas
  11. Line 10: Missing spaces after colons in dict ('x':0, 'y':2.0, 'z':1.5)
    • Rule: Use spaces after colons in dictionaries
  12. Line 11: Inconsistent constant naming (MAX_distance should be all caps)
    • Rule: Constants should use UPPER_CASE with underscores

Corrected Version

from dash import Dash, dcc, html
import numpy as np

def generate_road_profile(num_points=100, x_max=80):
    x = np.linspace(0, x_max, num_points)
    y = 0.015 * x**3 + 0.3 * np.sin(2 * np.pi * x)
    return x, y

camera_position = {'x': 0, 'y': 2.0, 'z': 1.5}
MAX_DISTANCE = 100

Key Takeaways

  • Import organization: alphabetize within grouped imports
  • Mathematical expressions need spaces around operators (except ** which is optional)
  • Dictionary formatting: {key: value} not {key:value}
  • Constant naming: ALL_UPPER_CASE for module-level constants

Exercise 2.3: Helper Functions

Problem

import numpy as np
from typing import List

def HelperFunction(val):
    result=val*2
    return result

def another_helper(x,y,z): return x+y+z

def calculate_distance(point1,point2):
    dx=point2[0]-point1[0]
    dy=point2[1]-point1[1]
    return np.sqrt(dx**2+dy**2)

# This is a very long comment that definitely exceeds the recommended 79 character limit for code readability

Questions

  1. List ALL PEP 8 violations (aim for 10-12 issues)
  2. For each issue, state the violated rule
  3. Write the fully corrected version

Challenge

This exercise tests your ability to spot:

💡 Show Solution

Issues Found

  1. Line 4: Function name uses PascalCase (HelperFunction)
    • Rule: Function names should use snake_case
  2. Line 5: Missing spaces around assignment operator (result=val*2)
    • Rule: Surround operators with spaces
  3. Line 5: Missing spaces around multiplication operator (val*2)
    • Rule: Surround binary operators with spaces
  4. Line 8: Missing spaces after commas (x,y,z)
    • Rule: Use spaces after commas
  5. Line 8: Multiple statements on one line after colon
    • Rule: Avoid compound statements
  6. Line 10: Missing spaces after commas (point1,point2)
    • Rule: Use spaces after commas
  7. Line 11: Missing spaces around assignment (dx=)
    • Rule: Surround operators with spaces
  8. Line 11: Missing spaces around subtraction operators
    • Rule: Surround binary operators with spaces
  9. Line 12: Missing spaces around assignment (dy=)
    • Rule: Surround operators with spaces
  10. Line 12: Missing spaces around subtraction operators
    • Rule: Surround binary operators with spaces
  11. Line 13: Missing spaces around addition operator (dx**2+dy**2)
    • Rule: Surround binary operators with spaces
  12. Line 15: Line too long (exceeds 79/88 character limit)
    • Rule: Limit lines to a maximum of 79 characters (or 88 with modern tools)

Corrected Version

import numpy as np
from typing import List

def helper_function(val):
    result = val * 2
    return result

def another_helper(x, y, z):
    return x + y + z

def calculate_distance(point1, point2):
    dx = point2[0] - point1[0]
    dy = point2[1] - point1[1]
    return np.sqrt(dx**2 + dy**2)

# This is a comment that has been properly broken into
# multiple lines for better readability

Key Takeaways

  • Function names: always use snake_case, never PascalCase
  • Compound statements hide logic and make debugging harder
  • Long comments should be broken across multiple lines
  • Consistent spacing makes mathematical expressions much more readable
  • Every operator deserves breathing room (except ** where it’s optional)

Exercise 2.4: Class Definition

Problem

import sys,os,json

class DataProcessor:
    def __init__(self,data,config=None):
        self.data=data
        self.config=config if config else {}
    
    def Process(self,threshold=0):
        filtered=[x for x in self.data if x>threshold]
        return filtered
    
    def GetStats(self):
        return {'mean':np.mean(self.data),'std':np.std(self.data)}

max_items=1000

Questions

  1. List ALL PEP 8 violations (aim for 12-15 issues)
  2. For each issue, state the violated rule
  3. Write the fully corrected version

Extra Challenge

Can you spot the bonus issue that’s not strictly PEP 8 but would cause a runtime error?

💡 Show Solution

Issues Found

  1. Line 1: Multiple imports on one line (sys,os,json)
    • Rule: Imports should be on separate lines
  2. Line 1: All three imports are unused
    • Rule: Remove unused imports
  3. Line 4: Missing spaces after commas (data,config)
    • Rule: Use spaces after commas
  4. Line 5: Missing spaces around assignment (self.data=data)
    • Rule: Surround operators with spaces
  5. Line 6: Missing spaces around assignment (self.config=config)
    • Rule: Surround operators with spaces
  6. Line 8: Method name uses PascalCase instead of snake_case (Process)
    • Rule: Method names should use snake_case
  7. Line 8: Missing space after comma (Process(self,threshold)
    • Rule: Use spaces after commas
  8. Line 9: Missing spaces around assignment (filtered=)
    • Rule: Surround operators with spaces
  9. Line 9: Missing spaces around comparison (x>threshold)
    • Rule: Surround binary operators with spaces
  10. Line 12: Method name uses PascalCase (GetStats)
    • Rule: Method names should use snake_case
  11. Line 13: Missing spaces after colons in dict ('mean':, 'std':)
    • Rule: Use spaces after colons in dictionaries
  12. Line 15: Variable should use UPPER_CASE (max_itemsMAX_ITEMS)
    • Rule: Module-level constants should use UPPER_CASE
  13. BONUS: np is used but never imported (would cause NameError)
    • Issue: Missing import numpy as np

Corrected Version

import numpy as np

class DataProcessor:
    def __init__(self, data, config=None):
        self.data = data
        self.config = config if config else {}
    
    def process(self, threshold=0):
        filtered = [x for x in self.data if x > threshold]
        return filtered
    
    def get_stats(self):
        return {'mean': np.mean(self.data), 'std': np.std(self.data)}

MAX_ITEMS = 1000

Key Takeaways

  • Import only what you use—unused imports are dead weight
  • Method names follow the same rules as function names: snake_case
  • Dictionary spacing: {key: value} creates clear key-value separation
  • Module-level constants use UPPER_CASE to signal “don’t modify”
  • Always test your code—PEP 8 doesn’t catch logic errors!

Exercise 2.5: Complex Function

Problem

from typing import List,Tuple
import numpy as np

def find_intersection(x_road,y_road,angle_degrees,camera_x=0,camera_y=1.5):
    angle_rad=np.radians(angle_degrees)
    ray_dx=np.cos(angle_rad)
    ray_dy=np.sin(angle_rad)
    
    for i in range(len(x_road)-1):
        x1,y1=x_road[i],y_road[i]
        x2,y2=x_road[i+1],y_road[i+1]
        
        # Check intersection - this calculation is complex and might need refactoring for better maintainability
        t=((camera_y-y1)*ray_dx-(camera_x-x1)*ray_dy)/((x2-x1)*ray_dy-(y2-y1)*ray_dx)
        
        if 0<=t<=1:
            x_intersect=x1+t*(x2-x1)
            return x_intersect,y1+t*(y2-y1)
    
    return None,None

Questions

  1. List ALL PEP 8 violations (aim for 15+ issues)
  2. For each issue, state the violated rule
  3. Write the fully corrected version

Expert Level

This is the most complex exercise. It contains violations in:

Take your time and be systematic!

💡 Show Solution

Issues Found

  1. Line 1: Multiple imports on one line (List,Tuple)
    • Rule: Imports should be on separate lines (applies to from imports too)
  2. Line 4: Missing spaces after commas in all parameters
    • Rule: Use spaces after commas (affects 4 commas)
  3. Line 5: Missing spaces around assignment (angle_rad=)
    • Rule: Surround operators with spaces
  4. Line 6: Missing spaces around assignment (ray_dx=)
    • Rule: Surround operators with spaces
  5. Line 7: Missing spaces around assignment (ray_dy=)
    • Rule: Surround operators with spaces
  6. Line 9: Missing spaces around subtraction (len(x_road)-1)
    • Rule: Surround binary operators with spaces
  7. Line 10: Missing spaces after commas (x1,y1 and x_road[i],y_road[i])
    • Rule: Use spaces after commas
  8. Line 11: Missing spaces after commas (same issue)
    • Rule: Use spaces after commas
  9. Line 11: Missing spaces around addition (i+1)
    • Rule: Surround binary operators with spaces
  10. Line 13: Line exceeds recommended length (>88 characters)
    • Rule: Limit lines to 79-88 characters
  11. Line 14: Missing spaces around assignment (t=)
    • Rule: Surround operators with spaces
  12. Line 14: Missing spaces around all operators in complex expression
    • Rule: Surround binary operators with spaces
  13. Line 16: Missing spaces around comparison operators (0<=t<=1)
    • Rule: Surround comparison operators with spaces
  14. Line 17: Missing spaces around assignment (x_intersect=)
    • Rule: Surround operators with spaces
  15. Line 17: Missing spaces around operators (x1+t*(x2-x1))
    • Rule: Surround binary operators with spaces
  16. Line 18: Missing spaces after comma and around operators
    • Rule: Use spaces after commas and around operators
  17. Line 20: Missing space after comma (None,None)
    • Rule: Use spaces after commas

Corrected Version

from typing import List, Tuple
import numpy as np

def find_intersection(
    x_road,
    y_road,
    angle_degrees,
    camera_x=0,
    camera_y=1.5
):
    angle_rad = np.radians(angle_degrees)
    ray_dx = np.cos(angle_rad)
    ray_dy = np.sin(angle_rad)
    
    for i in range(len(x_road) - 1):
        x1, y1 = x_road[i], y_road[i]
        x2, y2 = x_road[i + 1], y_road[i + 1]
        
        # Check intersection - this calculation is complex and might
        # need refactoring for better maintainability
        numerator = (camera_y - y1) * ray_dx - (camera_x - x1) * ray_dy
        denominator = (x2 - x1) * ray_dy - (y2 - y1) * ray_dx
        t = numerator / denominator
        
        if 0 <= t <= 1:
            x_intersect = x1 + t * (x2 - x1)
            return x_intersect, y1 + t * (y2 - y1)
    
    return None, None

Key Takeaways

  • Complex expressions: Break them into named intermediate variables
  • Long parameter lists: Use multi-line formatting for clarity
  • Mathematical code: Consistent spacing makes formulas readable
  • Comparison chains: 0 <= t <= 1 needs spaces around both operators
  • Refactoring bonus: Breaking complex calculations into steps aids debugging
  • Line length: When formulas are too long, introduce intermediate variables

Professional Enhancement

For production code, consider adding type hints and docstring:

from typing import Optional, Tuple
import numpy as np
import numpy.typing as npt

def find_intersection(
    x_road: npt.NDArray,
    y_road: npt.NDArray,
    angle_degrees: float,
    camera_x: float = 0,
    camera_y: float = 1.5
) -> Tuple[Optional[float], Optional[float]]:
    """
    Find intersection point between camera ray and road profile.
    
    Args:
        x_road: X coordinates of road profile points
        y_road: Y coordinates of road profile points
        angle_degrees: Ray angle in degrees from horizontal
        camera_x: Camera X position (default: 0)
        camera_y: Camera Y position (default: 1.5)
        
    Returns:
        Tuple of (x, y) intersection coordinates, or (None, None) if no intersection
    """
    # ... implementation ...

Exercise 2.6: Configuration Management

Problem

import json,sys
from pathlib import Path

class ConfigManager:
    def __init__(self,config_file="config.json"):
        self.config_file=config_file
        self.data=self.load_config()
    
    def load_config(self):
        if Path(self.config_file).exists():return json.load(open(self.config_file))
        return {}
    
    def get_value(self,key,default=None):
        return self.data.get(key,default)
    
    def update_config(self,updates):
        self.data.update(updates)
        with open(self.config_file,"w") as f:json.dump(self.data,f)

DEFAULT_timeout=30
max_retries=3

Questions

  1. List ALL PEP 8 violations (aim for 15+ issues)
  2. For each issue, state the violated rule
  3. Write the fully corrected version
💡 Show Solution

Issues Found

  1. Line 1: Multiple imports on one line (json,sys)
    • Rule: Imports should be on separate lines
  2. Line 1: Unused import (sys)
    • Rule: Remove unused imports
  3. Line 5: Missing space after comma in parameters (config_file="config.json")
    • Rule: Use spaces after commas
  4. Line 6: Missing spaces around assignment (self.config_file=)
    • Rule: Surround operators with spaces
  5. Line 7: Missing spaces around assignment (self.data=)
    • Rule: Surround operators with spaces
  6. Line 10: Compound statement after if (:return)
    • Rule: Avoid multiple statements on one line
  7. Line 10: File opened but never explicitly closed
    • Rule: Use context manager (with statement) for files
  8. Line 13: Missing spaces after commas in parameters (key,default)
    • Rule: Use spaces after commas
  9. Line 14: Missing space after comma in method call (key,default)
    • Rule: Use spaces after commas
  10. Line 17: Missing space after comma in parameters
    • Rule: Use spaces after commas
  11. Line 19: Missing space after comma in open() call ("w")
    • Rule: Use spaces after commas (though "w" is actually correct)
  12. Line 19: Compound statement after with (:json.dump)
    • Rule: Avoid multiple statements on one line
  13. Line 19: Missing space after comma in json.dump (data,f)
    • Rule: Use spaces after commas
  14. Line 21: Inconsistent constant naming (DEFAULT_timeout should be all caps)
    • Rule: Constants should use consistent UPPER_CASE
  15. Line 22: Variable should use UPPER_CASE (max_retriesMAX_RETRIES)
    • Rule: Module-level constants should use UPPER_CASE

Corrected Version

import json
from pathlib import Path

class ConfigManager:
    def __init__(self, config_file="config.json"):
        self.config_file = config_file
        self.data = self.load_config()
    
    def load_config(self):
        if Path(self.config_file).exists():
            with open(self.config_file) as f:
                return json.load(f)
        return {}
    
    def get_value(self, key, default=None):
        return self.data.get(key, default)
    
    def update_config(self, updates):
        self.data.update(updates)
        with open(self.config_file, "w") as f:
            json.dump(self.data, f)

DEFAULT_TIMEOUT = 30
MAX_RETRIES = 3

Key Takeaways

  • File handling: Always use with statements to ensure proper cleanup
  • Compound statements: They save lines but hurt readability and debugging
  • Consistent naming: All module-level constants should be UPPER_CASE
  • Method chaining: Each operation should be clearly visible on its own line
  • Resource management: Python’s context managers prevent resource leaks

Summary and Next Steps

What You’ve Learned

After completing these Level 2 exercises, you should be able to:

Spot multiple violations simultaneously in real code
Recognize patterns of related issues (e.g., all missing commas)
Prioritize issues by impact on readability
Apply systematic review techniques
Write cleaner code from the start

Progression Path

Level 1 (Single Issues)
    ↓
Level 2 (Multiple Issues) ← You are here
    ↓
Level 3 (Real-world Code)
    ↓
Automated Tools (Ruff, Black)
    ↓
Production Workflow (CI/CD)
  1. Daily Practice: Review 1-2 exercises per day
  2. Real Code: Apply these skills to your own projects
  3. Peer Review: Exchange code with classmates
  4. Before Tools: Master manual review before relying on automation
  5. Speed Building: Time yourself—aim for 5 minutes per exercise

Ready for More?


Study Tips

For Maximum Learning

  1. Write Down Your Answers
    • Don’t just think it—write it
    • Reinforces learning through motor memory
    • Creates a study reference
  2. Review Before Checking Solutions
    • Resist the urge to peek immediately
    • Struggle is part of learning
    • Compare your thoroughness with the answer
  3. Track Your Progress
    • Note which issues you consistently miss
    • Focus practice on weak areas
    • Celebrate improvements!
  4. Practice in Groups
    • Discuss findings with classmates
    • Learn from different perspectives
    • Teach others to reinforce your understanding
  5. Apply to Real Projects
    • Review your own past code
    • Fix violations you find
    • Notice how readability improves

Common Mistakes to Avoid

Checking solutions too quickly
Spend at least 5 minutes trying first

Memorizing violations
Understanding the “why” behind rules

Skipping exercises
Complete all exercises in order

Passive reading
Active practice with pen and paper


Assessment

Want to test your skills? Try this self-assessment:

Speed Test

Can you find all violations in Exercise 2.1 in under 3 minutes?

Accuracy Test

Complete Exercise 2.5 and aim for 15+ violations found.

Comprehension Test

Without looking, explain why each PEP 8 rule matters for team collaboration.


Feedback and Questions

Found an issue you disagree with? Have a question about a specific rule? Reach out during office hours or via the course forum.

Remember: The goal isn’t perfection—it’s developing a systematic approach to code quality that will serve you throughout your career.

Happy practicing! 🚀

© 2026 Dominik Mueller   •  Powered by Soopr   •  Theme  Moonwalk