PEP 8 is Python’s official style guide that provides coding conventions and best practices for writing clear, readable Python code. Adhering to PEP 8 principles enables writing uniform, easy-to-understand Python code that follows industry standards. This improves code maintainability and readability.
This guide will provide a comprehensive overview of PEP 8 recommendations and demonstrate practical code review and refactoring exercises developers can perform to identify and correct areas of improvement for applying PEP 8 principles in existing Python code.
Following the principles and techniques outlined in this guide will assist Python developers in writing high-quality Python code that conforms to the PEP 8 style guide. The concepts discussed are applicable for beginners learning Python and experienced developers working on Python projects in data science, machine learning, and software engineering domains.
Table of Contents
Open Table of Contents
Overview of Key PEP 8 Recommendations
Let us first briefly summarize some key PEP 8 recommendations related to Python code formatting and style conventions:
-
Indentation: Use 4 spaces for indentation, not tabs.
-
Maximum line length: Limit all lines to a maximum of 79 characters.
-
Blank lines: Surround top-level function and class definitions with two blank lines. Method definitions inside a class are surrounded by a single blank line.
-
Imports: Imports should be on separate lines.
-
Spaces: Always surround binary operators like assignments (
=
), comparisons (==
,>
,+=
, etc.) and arithmetic operators (+
,-
,*
,/
) with a single space on both sides. -
Naming Conventions:
-
Function, variable and attribute names should be in
lowercase_underscore
format. -
Protected instance attributes should be prefixed with a single underscore (
_
). -
Private instance attributes should be prefixed with double underscores (
__
). -
Class names should be in
CapitalizedWord
format. -
Module-level constants should be in
ALL_CAPS
format.
-
-
Comments: Comments should explain why something is done instead of what is being done. Limit line length to 72 characters for comments.
-
Docstrings: Use triple quotes
"""
for module, function, class and method docstrings.
These are some of the key recommendations from PEP 8 that directly impact code readability, maintainability and style. The complete PEP 8 style guide contains many more conventions. We will now see some practical exercises for reviewing code to identify deviations from PEP 8 and then refactor the code to align with PEP 8 principles.
Code Review Exercises
Let’s go through code review checklists and exercises to spot areas not conforming to PEP 8 recommendations:
Checklist for Module Level Code
- Module name complies with
short_lowercase_style
convention - Docstring provided explaining the module
- Imports on separate lines
- Constants in
ALL_CAPS
format - Spaces around operators like
=
and==
- Line length < 79 characters
- Two blank lines surround top level function and class definitions
Checklist for Functions and Methods
- Function and method names in
lowercase_underscore
format - Docstring provided explaining the function/method
- Spaces after commas separating arguments
- Default arguments specified by keyword, not position
- Single blank line separates def statements
- Line length < 79 characters
Checklist for Classes
- Class name follows
CapitalizedWord
convention - Docstring provided explaining the class
- Public methods follow conventions
- Underscores prefix non-public attributes and methods
- __init__ method specified if needed
- Spaces around operators like
=
and==
- Line length < 79 characters
- Single blank line separates class def statement
Checklist for Code Readability
- Code is properly indented with 4 spaces
- Related blocks separated by blank lines
- Whitespaces used appropriately to align code
- Variables and functions have appropriate descriptive names
- Code avoids hardcoding values, magic numbers
- Code has sufficient comments explaining intent
- Idiomatic Python code written leveraging best practices
Let’s apply these checklists to review the following sample code:
# Sample code
import os
CONST_VALUE = 10
def foo(x,y):
print(x+y)
class myClass:
def __init__(self):
self.x = 10
def myMethod(self, x, y):
return x + y
print(CONST_VALUE)
By going through the checklists, we can identify the following issues:
- Missing docstrings for module, function and class
- Imports not on separate lines
- Constant
CONST_VALUE
not in all caps - Spaces missing around operators
=
and+
myClass
should followCapitalizedWord
conventionmyMethod
should have underscore formatfoo
prints result instead of returning- Hardcoded value 10, no comments
This review helped spot many areas where the code deviates from PEP 8 conventions and principles. Similar checklist-driven reviews of existing code can help uncover areas for improvement.
Refactoring Exercises
Let’s now go through some refactoring exercises to fix the issues identified during the review and make the code PEP 8 compliant:
1. Add docstrings:
"""This module provides utility functions for math operations."""
def foo(x, y):
"""Prints the sum of two numbers."""
print(x + y)
class MyClass:
"""Represents a class to operate on some data."""
def __init__(self):
"""Initialize the class with default values."""
self.x = 10
def my_method(self, x, y):
"""Adds two numbers and returns the sum."""
return x + y
2. Fix imports, constant name and spacing:
"""This module provides utility functions for math operations."""
import os
CONST_VALUE = 10
def foo(x, y):
"""Prints the sum of two numbers."""
print(x + y)
class MyClass:
"""Represents a class to operate on some data."""
def __init__(self):
"""Initialize the class with default values."""
self.x = 10
def my_method(self, x, y):
"""Adds two numbers and returns the sum."""
return x + y
print(CONST_VALUE)
3. Make function return value rather than print:
def foo(x, y):
"""Returns the sum of two numbers."""
return x + y
4. Use descriptive names and remove hardcoded values:
MAX_RETRIES = 5
def calculate_sum(first_number, second_number):
"""Returns the sum of two numbers."""
return first_number + second_number
class DataClass:
"""Represents a class to operate on some data."""
def __init__(self):
"""Initialize the class with default values."""
self.number = 10
def add_numbers(self, first_num, second_num):
"""Adds two numbers and returns the sum."""
return first_num + second_num
These examples demonstrate how we can refactor existing code to fix PEP 8 issues identified during code review. The refactored code has proper spacing, naming conventions, docstrings, comments and style as per PEP 8 principles.
Refactoring Strategies
Let’s discuss some effective strategies for refactoring code to comply with PEP 8:
-
Improve code layout: Refactor code to use proper indentation, whitespaces, newlines and blank lines to enhance readability. Break long lines exceeding 79 char limit.
-
Add comments and docstrings: Provide comments explaining intention and docstrings for modules, classes and functions.
-
Use descriptive names: Rename variables, functions and classes with readable, lowercase names using underscores. Avoid abbreviations and unclear names.
-
Remove hardcoding: Replace hardcoded strings, integers, file paths, URLs, etc. with constants or config values.
-
Modularize code: Break large files into smaller modules with specific responsibilities according to concepts.
-
Leverage Python features: Use Pythonic language constructs like list comprehensions, generators, context managers etc. instead of complex nested loops and conditionals.
-
Refactor imports: Clean up imports to avoid importing unused modules. Use relative imports where appropriate.
-
Improve logic: Refactor repetitive logic, long methods, and complex conditionals to be more readable and extendable.
These refactoring techniques can help transform unstructured spaghetti code to modular, readable, Pythonic code conforming to PEP 8.
Automated PEP 8 Analysis Tools
Manually reviewing code for PEP 8 conformance has limitations. Automated tools can analyze code at scale and catch issues that may be missed during manual review.
Some popular automated PEP 8 analysis tools for Python include:
-
pycodestyle: Command line tool that analyzes Python source code against some of the PEP 8 style conventions.
-
Flake8: Extensible tool that examines Python code and detects style violations, programming errors etc. using pyflakes and pycodestyle.
-
Pylint: Provides extensive static analysis to check Python code against coding standards and bugs. Catches PEP 8 violations also.
-
autopep8: Formats Python code according to PEP 8 style guide automatically. Supports integrating with code editors.
These automated tools provide an objective PEP 8 conformance report for Python code. Developers should run these routinely during development to detect issues early. The tools also suggest fixes for certain categories of PEP 8 deviations.
However, automation cannot catch all readability, logic and organization issues. Manual code review is still needed along with running these tools.
Exercises for Readers
To master PEP 8 principles and improve your Python code quality, try these practice exercises:
-
Review a Python file or project you have written against the PEP 8 style guide and identify areas of improvement.
-
Take poorly formatted, undocumented Python code with non-standard naming conventions and refactor it to conform with PEP 8 principles.
-
Use a PEP 8 analysis tool like pycodestyle or Flake8 on your codebase and fix the issues reported incrementally.
-
Learn about opinionated formatter like Black or isort that can auto-format Python code to comply with PEP 8. Try it out on a sample project.
-
Contribute to open source Python projects on GitHub by reviewing others’ pull requests and providing feedback on PEP 8 issues.
-
Pay attention to PEP 8 principles during code review at work and coach other developers to write more Pythonic code.
Regular practice and application of these exercises will help ingrain good PEP 8 habits into your coding skills.
Conclusion
PEP 8 provides comprehensive style guidelines and best practices for writing high quality Python code that is readable, maintainable and consistent. Performing code reviews against PEP 8 checklists coupled with refactoring using recommended strategies enables bringing existing Python code up to standard. Automated analysis tools can catch additional issues at scale.
Adopting the code review, refactoring exercises and tools covered in this guide will help Python developers to consistently write code following PEP 8 principles. This will improve the professionalism, reliability and collaboration on Python codebases. The benefits of standards are multiplied on large projects with many developers.
As PEP 8 is considered the de facto coding standard for Python, practicing it regularly is an essential skill for any Python programmer. The techniques presented in this guide should provide a useful methodology to assess and improve PEP 8 conformance of Python code in any environment.