Python development best practices including PEP 8 style guidelines, type hints, docstring conventions, and common patterns. Use when writing or modifying Python code.
This skill provides guidance on Python development best practices to ensure code quality, maintainability, and consistency across your Python projects.
Auto-activates when:
Follow PEP 8 style guide for Python code:
snake_case for functions, variables, modulesPascalCase for classesUPPER_SNAKE_CASE for constants_name for internal/privateAlways organize imports in this order:
# 1. Standard library imports
import os
import sys
from pathlib import Path
# 2. Third-party imports
import requests
import numpy as np
# 3. Local application imports
from myapp.core import MyClass
from myapp.utils import helper_function
Avoid circular imports by using TYPE_CHECKING:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from myapp.other_module import OtherClass
def my_function(obj: "OtherClass") -> None:
"""Function that uses OtherClass only for type hints."""
pass
Type hints improve code clarity and catch errors early:
def process_data(
items: list[str],
max_count: int | None = None,
verbose: bool = False
) -> dict[str, int]:
"""Process items and return counts.
Parameters
----------
items : list[str]
List of items to process
max_count : int | None, optional
Maximum items to process, by default None
verbose : bool, optional
Enable verbose output, by default False
Returns
-------
dict[str, int]
Dictionary mapping items to counts
"""
result: dict[str, int] = {}
for item in items[:max_count]:
result[item] = result.get(item, 0) + 1
if verbose:
print(f"Processed: {item}")
return result
Use modern union syntax with | instead of Union:
# Good (Python 3.10+)
def get_value(key: str) -> int | None:
pass
# Avoid (old style)
from typing import Union, Optional
def get_value(key: str) -> Optional[int]:
pass
Use built-in generic types (Python 3.9+):
# Good (Python 3.9+)
def process_list(items: list[str]) -> dict[str, int]:
pass
# Avoid (old style)
from typing import List, Dict
def process_list(items: List[str]) -> Dict[str, int]:
pass
Use NumPy-style docstrings for consistency:
def calculate_statistics(
data: list[float],
include_median: bool = True
) -> dict[str, float]:
"""Calculate statistical measures for a dataset.
This function computes mean, standard deviation, and optionally
median for the provided dataset.
Parameters
----------
data : list[float]
List of numerical values to analyze
include_median : bool, optional
Whether to calculate median, by default True
Returns
-------
dict[str, float]
Dictionary containing:
- 'mean': arithmetic mean
- 'std': standard deviation
- 'median': median value (if include_median=True)
Raises
------
ValueError
If data is empty or contains non-numeric values
Examples
--------
>>> calculate_statistics([1.0, 2.0, 3.0, 4.0, 5.0])
{'mean': 3.0, 'std': 1.414, 'median': 3.0}
Notes
-----
Standard deviation uses Bessel's correction (ddof=1).
"""
if not data:
raise ValueError("Data cannot be empty")
# Implementation here
pass
class DataProcessor:
"""Process and transform data from various sources.
This class provides methods for loading, transforming, and
validating data from multiple input formats.
Parameters
----------
source_dir : Path
Directory containing source data files
cache_enabled : bool, optional
Enable result caching, by default True
Attributes
----------
source_dir : Path
Directory path for source files
cache : dict[str, Any]
Cache for processed results
Examples
--------
>>> processor = DataProcessor(Path("/data"))
>>> results = processor.process_files()
"""
def __init__(self, source_dir: Path, cache_enabled: bool = True):
"""Initialize the DataProcessor."""
self.source_dir = source_dir
self.cache: dict[str, Any] = {} if cache_enabled else None
Use specific exception types, not bare except:
# Good