02 Exercise: PEP 8 - Level 2: Multiple Issues
October 2025 (4462 Words, 25 Minutes)
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:
- Identify 3-5 PEP 8 violations in a single code snippet
- Understand how multiple style issues compound readability problems
- Practice systematic code review skills
- Build confidence in recognizing patterns
Instructions:
- Read each code example carefully
- Try to find ALL PEP 8 violations before checking the solution
- Write down your answers (recommended for learning)
- Click “Show Solution” only after you’ve attempted the exercise
- 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
- List ALL PEP 8 violations (aim for 5-7 issues)
- For each issue, state the violated rule
- Write the fully corrected version
Your Turn
Before checking the solution, try to:
- List each violation you find
- Note the line number for each issue
- Write the corrected code yourself
💡 Show Solution
Issues Found
- Line 1: Multiple imports on one line (
sys,os)- Rule: Imports should usually be on separate lines
- Line 1: Unused imports (
sysandosare never used)- Rule: Remove unused imports to keep code clean
- Line 4: Function name uses PascalCase instead of snake_case (
ProcessData)- Rule: Function names should be lowercase with words separated by underscores
- Line 4: Missing space after comma in parameters (
input_list,threshold)- Rule: Use spaces after commas in parameter lists
- Line 5: Missing spaces around assignment operator (
result=[])- Rule: Always surround operators with a single space on either side
- Line 7: Missing spaces around comparison operator (
item>threshold)- Rule: Always surround binary operators with spaces
- 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
- List ALL PEP 8 violations (aim for 10-12 issues)
- For each issue, state the violated rule
- Write the fully corrected version
Hints
- Check import statements carefully
- Look for spacing issues around operators
- Examine dictionary formatting
- Consider constant naming conventions
💡 Show Solution
Issues Found
- Line 1: Multiple imports on one line (
Dash,html,dcc)- Rule: Imports should be on separate lines
- Line 1: Missing spaces after commas in import
- Rule: Use spaces after commas
- Line 3: Unused import (
sys)- Rule: Remove unused imports
- Line 5: Missing space after comma in parameters (
num_points=100,x_max=80)- Rule: Use spaces after commas
- Line 6: Missing spaces around assignment (
x=)- Rule: Surround operators with spaces
- Line 6: Missing spaces after commas (
0,x_max,num_points)- Rule: Use spaces after commas
- Line 7: Missing spaces around assignment (
y=)- Rule: Surround operators with spaces
- Line 7: Missing spaces around multiplication operators (
0.015*x,0.3*np.sin)- Rule: Surround binary operators with spaces
- Line 7: Missing spaces around addition operator (
x**3+0.3)- Rule: Surround binary operators with spaces
- Line 8: Missing space after comma in return (
x,y)- Rule: Use spaces after commas
- Line 10: Missing spaces after colons in dict (
'x':0,'y':2.0,'z':1.5)- Rule: Use spaces after colons in dictionaries
- Line 11: Inconsistent constant naming (
MAX_distanceshould 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
- List ALL PEP 8 violations (aim for 10-12 issues)
- For each issue, state the violated rule
- Write the fully corrected version
Challenge
This exercise tests your ability to spot:
- Naming convention violations
- Whitespace issues in multiple contexts
- Line length problems
- Compound statement issues
💡 Show Solution
Issues Found
- Line 4: Function name uses PascalCase (
HelperFunction)- Rule: Function names should use snake_case
- Line 5: Missing spaces around assignment operator (
result=val*2)- Rule: Surround operators with spaces
- Line 5: Missing spaces around multiplication operator (
val*2)- Rule: Surround binary operators with spaces
- Line 8: Missing spaces after commas (
x,y,z)- Rule: Use spaces after commas
- Line 8: Multiple statements on one line after colon
- Rule: Avoid compound statements
- Line 10: Missing spaces after commas (
point1,point2)- Rule: Use spaces after commas
- Line 11: Missing spaces around assignment (
dx=)- Rule: Surround operators with spaces
- Line 11: Missing spaces around subtraction operators
- Rule: Surround binary operators with spaces
- Line 12: Missing spaces around assignment (
dy=)- Rule: Surround operators with spaces
- Line 12: Missing spaces around subtraction operators
- Rule: Surround binary operators with spaces
- Line 13: Missing spaces around addition operator (
dx**2+dy**2)- Rule: Surround binary operators with spaces
- 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
- List ALL PEP 8 violations (aim for 12-15 issues)
- For each issue, state the violated rule
- 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
- Line 1: Multiple imports on one line (
sys,os,json)- Rule: Imports should be on separate lines
- Line 1: All three imports are unused
- Rule: Remove unused imports
- Line 4: Missing spaces after commas (
data,config)- Rule: Use spaces after commas
- Line 5: Missing spaces around assignment (
self.data=data)- Rule: Surround operators with spaces
- Line 6: Missing spaces around assignment (
self.config=config)- Rule: Surround operators with spaces
- Line 8: Method name uses PascalCase instead of snake_case (
Process)- Rule: Method names should use snake_case
- Line 8: Missing space after comma (
Process(self,threshold)- Rule: Use spaces after commas
- Line 9: Missing spaces around assignment (
filtered=)- Rule: Surround operators with spaces
- Line 9: Missing spaces around comparison (
x>threshold)- Rule: Surround binary operators with spaces
- Line 12: Method name uses PascalCase (
GetStats)- Rule: Method names should use snake_case
- Line 13: Missing spaces after colons in dict (
'mean':,'std':)- Rule: Use spaces after colons in dictionaries
- Line 15: Variable should use UPPER_CASE (
max_items→MAX_ITEMS)- Rule: Module-level constants should use UPPER_CASE
- BONUS:
npis used but never imported (would causeNameError)- Issue: Missing
import numpy as np
- Issue: Missing
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
- List ALL PEP 8 violations (aim for 15+ issues)
- For each issue, state the violated rule
- Write the fully corrected version
Expert Level
This is the most complex exercise. It contains violations in:
- Import statements
- Function parameters
- Variable assignments
- Mathematical expressions
- Comparison operators
- Comments
- Return statements
Take your time and be systematic!
💡 Show Solution
Issues Found
- Line 1: Multiple imports on one line (
List,Tuple)- Rule: Imports should be on separate lines (applies to
fromimports too)
- Rule: Imports should be on separate lines (applies to
- Line 4: Missing spaces after commas in all parameters
- Rule: Use spaces after commas (affects 4 commas)
- Line 5: Missing spaces around assignment (
angle_rad=)- Rule: Surround operators with spaces
- Line 6: Missing spaces around assignment (
ray_dx=)- Rule: Surround operators with spaces
- Line 7: Missing spaces around assignment (
ray_dy=)- Rule: Surround operators with spaces
- Line 9: Missing spaces around subtraction (
len(x_road)-1)- Rule: Surround binary operators with spaces
- Line 10: Missing spaces after commas (
x1,y1andx_road[i],y_road[i])- Rule: Use spaces after commas
- Line 11: Missing spaces after commas (same issue)
- Rule: Use spaces after commas
- Line 11: Missing spaces around addition (
i+1)- Rule: Surround binary operators with spaces
- Line 13: Line exceeds recommended length (>88 characters)
- Rule: Limit lines to 79-88 characters
- Line 14: Missing spaces around assignment (
t=)- Rule: Surround operators with spaces
- Line 14: Missing spaces around all operators in complex expression
- Rule: Surround binary operators with spaces
- Line 16: Missing spaces around comparison operators (
0<=t<=1)- Rule: Surround comparison operators with spaces
- Line 17: Missing spaces around assignment (
x_intersect=)- Rule: Surround operators with spaces
- Line 17: Missing spaces around operators (
x1+t*(x2-x1))- Rule: Surround binary operators with spaces
- Line 18: Missing spaces after comma and around operators
- Rule: Use spaces after commas and around operators
- 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 <= 1needs 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
- List ALL PEP 8 violations (aim for 15+ issues)
- For each issue, state the violated rule
- Write the fully corrected version
💡 Show Solution
Issues Found
- Line 1: Multiple imports on one line (
json,sys)- Rule: Imports should be on separate lines
- Line 1: Unused import (
sys)- Rule: Remove unused imports
- Line 5: Missing space after comma in parameters (
config_file="config.json")- Rule: Use spaces after commas
- Line 6: Missing spaces around assignment (
self.config_file=)- Rule: Surround operators with spaces
- Line 7: Missing spaces around assignment (
self.data=)- Rule: Surround operators with spaces
- Line 10: Compound statement after if (
:return)- Rule: Avoid multiple statements on one line
- Line 10: File opened but never explicitly closed
- Rule: Use context manager (
withstatement) for files
- Rule: Use context manager (
- Line 13: Missing spaces after commas in parameters (
key,default)- Rule: Use spaces after commas
- Line 14: Missing space after comma in method call (
key,default)- Rule: Use spaces after commas
- Line 17: Missing space after comma in parameters
- Rule: Use spaces after commas
- Line 19: Missing space after comma in open() call (
"w")- Rule: Use spaces after commas (though
"w"is actually correct)
- Rule: Use spaces after commas (though
- Line 19: Compound statement after with (
:json.dump)- Rule: Avoid multiple statements on one line
- Line 19: Missing space after comma in json.dump (
data,f)- Rule: Use spaces after commas
- Line 21: Inconsistent constant naming (
DEFAULT_timeoutshould be all caps)- Rule: Constants should use consistent UPPER_CASE
- Line 22: Variable should use UPPER_CASE (
max_retries→MAX_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
withstatements 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)
Recommended Practice
- Daily Practice: Review 1-2 exercises per day
- Real Code: Apply these skills to your own projects
- Peer Review: Exchange code with classmates
- Before Tools: Master manual review before relying on automation
- Speed Building: Time yourself—aim for 5 minutes per exercise
Ready for More?
- Level 3 Exercises: Real-world code examples (coming soon)
- Before/After Comparisons: See transformations in action
- Automated Tools: Introduction to Ruff and Black
- CI/CD Integration: Enforce quality automatically
Study Tips
For Maximum Learning
- Write Down Your Answers
- Don’t just think it—write it
- Reinforces learning through motor memory
- Creates a study reference
- Review Before Checking Solutions
- Resist the urge to peek immediately
- Struggle is part of learning
- Compare your thoroughness with the answer
- Track Your Progress
- Note which issues you consistently miss
- Focus practice on weak areas
- Celebrate improvements!
- Practice in Groups
- Discuss findings with classmates
- Learn from different perspectives
- Teach others to reinforce your understanding
- 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! 🚀