Python is widely known for its readability and clean syntax. Much of this reputation comes from PEP 8 — the official style guide for the language. Created by Guido van Rossum, Barry Warsaw, and Nick Coghlan, PEP 8 establishes conventions that make Python code uniform and easy to understand, regardless of who wrote it.

In this complete guide, you'll learn all the essential PEP 8 rules, from naming conventions and import organization to indentation, spacing, and beyond. If you want to write professional Python code and follow community best practices, this article is for you.

What Is PEP 8?

PEP stands for Python Enhancement Proposal. These are documents that propose improvements, new features, or standards for the Python language. PEP 8 is proposal number 8 and defines the official style guide for Python code.

Following PEP 8 is not required for your code to work — the Python interpreter doesn't validate style. However, it's considered a fundamental best practice for any professional developer. Open source projects, companies, and Python's own standard library all follow PEP 8 rigorously.

You can browse the full list of PEPs at the official Python PEP index.

Why Follow PEP 8?

Adopting PEP 8 delivers concrete benefits for you and your team:

  • Readability: consistent code is easier to read and understand
  • Maintainability: other developers can maintain your code without friction
  • Collaboration: reduces friction in code reviews and contributions
  • Professionalism: demonstrates mastery of community practices
  • Tooling: linters and formatters can automate style verification

Companies like Google, Instagram, and Spotify require their teams to follow PEP 8. If you want to work professionally with Python, mastering these conventions is essential.

Indentation

Indentation is one of the most well-known PEP 8 rules. Python uses indentation to define code blocks, unlike languages such as C or Java that use braces.

4 Spaces Per Level

Use 4 spaces for each indentation level. Never mix tabs and spaces. Configure your editor to insert spaces automatically when you press Tab.

# Correct — 4 spaces
def function():
    if condition:
        print("Indented with 4 spaces")

Wrong — mixed

def function(): if condition: print("Inconsistent indentation")

Vertical Alignment

For long lines, you can align elements vertically with the opening delimiter:

# Vertical alignment
result = calculate_value(first_parameter,
                         second_parameter,
                         third_parameter)

Hanging Indent

Use 4 extra spaces for hanging indentation:

# Hanging indent with extra indentation
result = calculate_value(
    first_parameter,
    second_parameter,
    third_parameter
)

Maximum Line Length

PEP 8 recommends a limit of 79 characters per line for code and 72 characters for comments and docstrings. This limit allows viewing multiple files side by side without horizontal scrolling.

# Line within the 79-character limit
def my_function(param_one, param_two, param_three):
    pass

Line break using backslash

result = value1 + value2 + value3 \

  • value4 + value5

In practice, many teams adopt 88 or 100 characters. The Black formatter, for example, defaults to 88 characters.

Blank Lines

Using blank lines improves readability:

  • Two blank lines between top-level function and class definitions
  • One blank line between methods inside a class
  • One blank line to separate logical sections inside a function
import os
import sys

def function_one(): """First function in the module.""" pass

def function_two(): """Second function in the module.""" pass

Imports

Imports should be organized into sections in the following order:

  1. Python standard library
  2. Third-party libraries
  3. Local project modules

Each group must be separated by a blank line. Within each group, imports should be alphabetically ordered.

# Correct
import os
import sys
from collections import defaultdict
from pathlib import Path

import requests from flask import Flask

from my_project.models import User from my_project.utils import format_date

Wrong — out of order

from flask import Flask import os from my_project.models import User import requests

Avoid wildcard imports (from module import *), as they pollute the namespace and make it harder to identify where names come from.

Naming Conventions

PEP 8 defines clear naming patterns for different code elements:

Variables and Functions

Use snake_case with lowercase letters and underscores for compound words:

# Correct
full_name = "John Doe"
def calculate_total(items):
    pass

Wrong

fullName = "John Doe" def CalculateTotal(items): pass

Constants

Use uppercase letters with underscores:

# Correct
MAX_ATTEMPTS = 3
INTEREST_RATE = 0.15

Wrong

max_attempts = 3 interest_rate = 0.15

Classes

Use PascalCase (also known as CapitalizedWords):

# Correct
class VipClient:
    pass

class DatabaseConnection: pass

Wrong

class vipClient: pass

class database_connection: pass

Private Methods and Attributes

Prefix with a single underscore to indicate internal use:

class Client:
    def __init__(self):
        self._balance = 0  # convention for private attribute
def _calculate_discount(self):  # internal method
    pass

Name Mangling (Double Underscore)

Use __name for name mangling, useful to avoid conflicts in inheritance:

class Account:
    def __init__(self):
        self.__balance = 0  # internally becomes _Account__balance

Names to Avoid

Never use l (lowercase L), O (uppercase O), or I (uppercase I) as variable names, as they can be confused with 1, 0, and 1 respectively.

# Wrong — hard to read
l = 1
O = 0
I = 1

Correct

line = 1 zero = 0 index = 1

Whitespace in Operators

PEP 8 has specific rules for whitespace around operators:

Always use spaces:

  • After commas: items = [1, 2, 3]
  • Around assignment operators: x = 5
  • Around comparison operators: if x == 5:
  • Around boolean operators: if x and y:
  • In function parameters with default values: def func(x=5):

Never use spaces:

  • Inside parentheses, brackets, or braces: spam(ham[1], {key: value})
  • Between function name and opening parenthesis: function()
  • Before commas or colons: if x == 5: and range(1, 10)
  • In slicing: items[0:5]
# Correct
result = a + b * c
dictionary = {"key": "value"}
function(param1, param2)
if value > 10:
    print("Greater than 10")

Wrong

result = a+b*c dictionary = {"key":"value"} function( param1, param2 ) if value>10: print("Greater than 10")

Comments and Docstrings

Comments should explain the why behind the code, not what it does — that should be clear from the code itself.

Inline Comments

Use # followed by a space. Overly long comments should be avoided; prefer refactoring the code to make it self-explanatory.

# Calculate total with progressive discount
total = sum(items) * (1 - discount)

Docstrings

Docstrings document modules, classes, functions, and methods. Follow the PEP 257 conventions for docstrings:

def calculate_average(numbers):
    """Calculates the arithmetic mean of a list of numbers.
Args:
    numbers: List of integers or floats.

Returns:
    The arithmetic mean of the provided numbers.
"""
return sum(numbers) / len(numbers)

Programming Conventions

PEP 8 also includes recommendations on programming patterns:

  • None comparisons: use if x is None instead of if x == None
  • Boolean comparisons: use if not x instead of if x == False
  • Empty sequence checks: use if not sequence: instead of if len(sequence) == 0:
  • Explicit returns: prefer return None over bare return or omitting the return
# Correct
if result is None:
    print("No result")

if not items: print("Empty list")

if error_occurred: return

Wrong

if result == None: print("No result")

if len(items) == 0: print("Empty list")

Tools to Automate PEP 8

You don't need to memorize every PEP 8 rule. Automated tools check and fix your code's style automatically:

Black

Black is the official Python code formatter. It reformats your code automatically to comply with PEP 8, without asking. It's known as "the uncompromising formatter."

pip install black
black my_file.py

Flake8

Flake8 is a linter that checks your code against PEP 8 and reports violations. It combines PyFlakes, pycodestyle, and McCabe.

pip install flake8
flake8 my_file.py

Pylint

Pylint is a more comprehensive linter that checks not only style but also logical errors, conventions, and code quality.

pip install pylint
pylint my_file.py

Editor Integration

Major code editors offer native or extension-based support:

  • VS Code: install the Python extension and enable "Format on Save" to use Black
  • PyCharm: PyCharm comes with built-in PEP 8 checking and can auto-format with Ctrl+Alt+L
  • pre-commit hooks: use pre-commit to run Black and Flake8 automatically before every commit

Setting Up a PEP 8 Project

Here's a quick guide to configuring your Python project with style tools:

# Install the tools
pip install black flake8 pylint

Create pyproject.toml to configure Black

[tool.black]

line-length = 88

target-version = ['py312']

Create .flake8 to configure Flake8

[flake8]

max-line-length = 88

extend-ignore = E203, W503

Once configured, run Black regularly and keep Flake8 in your CI/CD pipeline to ensure every pull request follows PEP 8 before merging.

PEP 8 and Type Hints

PEP 8 was complemented by PEP 484, which introduced type hints to Python. Type hints improve readability and let tools like mypy perform static type checking. Check out our complete guide on Python Type Hints to master this technique.

from typing import List, Optional

def process_data(name: str, items: List[int]) -> Optional[float]: """Processes data with type hints following PEP 8.""" if not items: return None return sum(items) / len(items)

Conclusion

PEP 8 is much more than a set of arbitrary rules — it is the expression of Python's philosophy: readable code is quality code. Following the official style guide makes your code more consistent, professional, and maintainable.

Remember: nobody memorizes every PEP 8 rule. The key is to understand the principles and use tools like Black, Flake8, and Pylint to automate compliance. Start by applying the naming conventions and import organization, and the rest will come naturally with practice.

To go deeper into best practices, also check our article on Clean Code in Python, which covers complementary principles for writing high-quality professional code.

Did you find this guide helpful? Share it with other developers and help the Python community write better code!