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:
- Python standard library
- Third-party libraries
- 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:andrange(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 Noneinstead ofif x == None - Boolean comparisons: use
if not xinstead ofif x == False - Empty sequence checks: use
if not sequence:instead ofif len(sequence) == 0: - Explicit returns: prefer
return Noneover barereturnor 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!