python-by-example/10_best_practices/01_pep8.py
2025-12-30 08:50:00 +02:00

335 lines
8.5 KiB
Python

"""
================================================================================
File: 01_pep8.py
Topic: PEP 8 - Python Style Guide
================================================================================
This file demonstrates PEP 8, the official Python style guide. Following PEP 8
makes your code more readable, consistent, and professional. These are
conventions, not strict rules, but following them is highly recommended.
Key Concepts:
- Indentation and whitespace
- Naming conventions
- Line length and wrapping
- Imports organization
- Comments and docstrings
Reference: https://peps.python.org/pep-0008/
================================================================================
"""
# =============================================================================
# 1. INDENTATION
# =============================================================================
# Use 4 spaces per indentation level. Never mix tabs and spaces.
# GOOD
def function_with_proper_indentation():
if True:
for i in range(10):
print(i)
# Aligned with opening delimiter
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Hanging indent (add a level)
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# =============================================================================
# 2. LINE LENGTH
# =============================================================================
# Limit lines to 79 characters (72 for docstrings/comments)
# GOOD - Use implicit line continuation
total = (first_variable
+ second_variable
+ third_variable)
# GOOD - Use backslash when necessary
with open('/very/long/path/to/file.txt') as file_one, \
open('/another/long/path/to/file.txt') as file_two:
pass
# =============================================================================
# 3. BLANK LINES
# =============================================================================
# - 2 blank lines around top-level functions and classes
# - 1 blank line between methods in a class
class FirstClass:
"""First class."""
pass
class SecondClass:
"""Second class."""
def method_one(self):
"""First method."""
pass
def method_two(self):
"""Second method."""
pass
def top_level_function():
"""A top-level function."""
pass
# =============================================================================
# 4. IMPORTS
# =============================================================================
# - One import per line
# - Group in order: standard library, third-party, local
# - Use absolute imports
# GOOD
import os
import sys
from typing import List, Optional
# Third party imports (after blank line)
# import numpy as np
# import pandas as pd
# Local imports (after blank line)
# from mypackage import mymodule
# BAD - Multiple imports on one line
# import os, sys
# =============================================================================
# 5. WHITESPACE
# =============================================================================
# GOOD - No extra whitespace inside brackets
spam = [1, 2, 3]
ham = {"key": "value"}
eggs = (1,)
# BAD
# spam = [ 1, 2, 3 ]
# ham = { 'key': 'value' }
# GOOD - One space around operators
x = 1
y = 2
z = x + y
# BAD - No space around = in keyword arguments
# def function(x, y = 5):
def function(x, y=5):
pass
# GOOD - Space after comma
some_list = [1, 2, 3]
# GOOD - No space before colon in slices
some_list[1:3]
some_list[::2]
# =============================================================================
# 6. NAMING CONVENTIONS
# =============================================================================
# Variables and functions: lowercase_with_underscores (snake_case)
user_name = "John"
total_count = 42
def calculate_average(numbers):
return sum(numbers) / len(numbers)
# Constants: UPPERCASE_WITH_UNDERSCORES
MAX_BUFFER_SIZE = 4096
DEFAULT_TIMEOUT = 30
PI = 3.14159
# Classes: CapitalizedWords (PascalCase)
class UserAccount:
pass
class HttpConnection:
pass
# Private: prefix with underscore
_internal_variable = "private"
def _internal_function():
pass
class MyClass:
def _protected_method(self):
"""Single underscore = protected (convention)."""
pass
def __private_method(self):
"""Double underscore = name mangling (truly private)."""
pass
# =============================================================================
# 7. COMMENTS
# =============================================================================
# GOOD - Inline comments have at least 2 spaces before #
x = 5 # This is an inline comment
# Block comments precede the code they describe
# This is a block comment that explains
# the following piece of code.
complex_calculation = 1 + 2 + 3
# Don't state the obvious
# BAD: x = 5 # Assign 5 to x
# GOOD: x = 5 # Default timeout in seconds
# =============================================================================
# 8. DOCSTRINGS
# =============================================================================
def example_function(param1, param2):
"""
Brief description of the function.
Longer description if needed. Explain what the function
does, not how it does it.
Args:
param1: Description of first parameter
param2: Description of second parameter
Returns:
Description of what is returned
Raises:
ValueError: When param1 is negative
Example:
>>> example_function(1, 2)
3
"""
return param1 + param2
class ExampleClass:
"""Brief description of the class.
Longer description of the class including its purpose
and usage patterns.
Attributes:
attr1: Description of first attribute
attr2: Description of second attribute
"""
def __init__(self, attr1, attr2):
"""Initialize ExampleClass."""
self.attr1 = attr1
self.attr2 = attr2
# =============================================================================
# 9. COMPARISON AND BOOLEAN
# =============================================================================
# Use 'is' and 'is not' for None comparisons
# GOOD
x = None
if x is None:
pass
# BAD
# if x == None:
# Use 'is not' instead of 'not ... is'
# GOOD
if x is not None:
pass
# BAD
# if not x is None:
# Don't compare boolean values with == or !=
# GOOD
flag = True
if flag:
pass
# BAD
# if flag == True:
# if flag is True: # Only use when testing identity
# =============================================================================
# 10. EXCEPTION HANDLING
# =============================================================================
# Catch specific exceptions
# GOOD
try:
value = int(user_input)
except ValueError:
print("Invalid input")
# BAD - Too broad
# try:
# value = int(user_input)
# except: # or except Exception:
# print("Error")
# Use 'raise' to re-raise exception
try:
process_data()
except ValueError:
logger.error("Bad value")
raise
# =============================================================================
# 11. FUNCTION ANNOTATIONS (Type Hints)
# =============================================================================
def greeting(name: str) -> str:
"""Return a greeting."""
return f"Hello, {name}!"
# Complex types
from typing import List, Dict, Optional
def process_items(
items: List[str],
config: Dict[str, int],
default: Optional[str] = None
) -> bool:
"""Process items with configuration."""
return True
# =============================================================================
# 12. SUMMARY: KEY RULES
# =============================================================================
print("PEP 8 Summary - Key Rules:")
print("""
1. Use 4 spaces for indentation
2. Limit lines to 79 characters
3. Use blank lines to separate functions and classes
4. Organize imports: standard lib, third-party, local
5. Use snake_case for functions and variables
6. Use PascalCase for classes
7. Use UPPER_CASE for constants
8. Use spaces around operators and after commas
9. Write docstrings for all public modules, functions, classes
10. Compare with 'is' for None, use bool directly
""")
# Use flake8 or black to automatically check/format code
print("Tools to help with PEP 8:")
print(" - flake8: Check for PEP 8 violations")
print(" - black: Automatic code formatting")
print(" - isort: Sort imports automatically")
print(" - pylint: Comprehensive code analysis")