Project Style Guide
This Python style guide provides conventions and best practices for writing clean and maintainable Python code. Adhering to these guidelines will help ensure consistency across projects and enhance the clarity, maintainability, and readability of the code.
Table of Contents
PEP 8
Adhere to the PEP 8 style guide, which is the style guide for Python code. Please make sure to familiarize yourself with PEP 8 guidelines: PEP 8 – Style Guide for Python Code.
Line Length
The maximum line length for code and comments is set to 120 characters. This allows for better readability without excessively long lines.
Naming Conventions
Classes
Class names should follow the CamelCase convention.
Class names should be descriptive and represent a clear concept or object.
Example:
class Calculator: def __init__(self): # Constructor implementation def add(self, x, y): # Method implementation
Functions
Function names should be lowercase, with words separated by underscores.
Function names should begin with a verb to indicate the action or operation they perform.
Examples:
def calculate_sum(numbers): """Calculate the sum of a list of numbers.""" # Function implementation def validate_input(user_input): """Validate user input and return True if valid, False otherwise.""" # Function implementation def process_data(data): """Process the given data and return the result.""" # Function implementation
Variables
Choosing meaningful and consistent variable names is essential for code readability. Follow these conventions:
Use lowercase letters with underscores for variable names (snake_case).
Be descriptive and use meaningful names to indicate the purpose of the variable.
Examples:
# Good variable names user_name = "John" num_items = 5 total_amount = 100.50 # Avoid ambiguous or single-letter names a = "John" # Not recommended n = 5 # Not recommended
Constants should be in uppercase with underscores.
Examples:
MAX_RETRIES = 3 PI = 3.14159
Avoid using names that shadow built-in functions or keywords.
Example:
# Bad: Don't use 'list' as a variable name list = [1, 2, 3] # Good: Choose a different name my_list = [1, 2, 3]
Use meaningful prefixes and suffixes for variable names where applicable.
Example:
# Prefix 'is_' for boolean variables is_valid = True # Suffix iterators with type (such as '_list') name_list = ["John", "Mary", "Robert", "Sue"]
Docstrings
Documenting your code is crucial for understanding its functionality and usage. Use Google-style docstrings to provide clear and concise documentation.
Module Docstring
Include a module-level docstring at the beginning of each Python file.
Use triple double-quotes for multi-line docstrings.
Example:
"""Module-level docstring. This module provides utility functions for handling calculations. """ # Rest of the module code
Class Docstring
Include a class-level docstring immediately below the class definition.
Briefly describe the purpose and usage of the class.
Example:
class Calculator: """A simple calculator class. This class provides basic arithmetic operations such as addition and subtraction. """ def __init__(self): # Constructor implementation
Function Docstring
Include a function-level docstring immediately below the function definition.
Provide a clear description of the function’s purpose, parameters, and return values.
Example:
def calculate_sum(numbers): """Calculate the sum of a list of numbers. Args: numbers (list): A list of numerical values. Returns: float: The sum of the input numbers. """ # Function implementation
Typing
Python’s optional type hints, introduced in PEP 484 and expanded in subsequent PEPs, provide a way to statically indicate the type of variables and function parameters. Proper use of typing can enhance code readability, maintainability, and catch certain types of errors early in the development process.
General Guidelines
Use Type Hints:
Type hints should be used consistently to indicate the expected types of variables and function parameters.
Example:
def add_numbers(a: int, b: int) -> int: return a + b
Avoid Redundant Type Hints:
Avoid providing type hints when the type is obvious from the variable name or the context.
Example:
# Good name: str = "John" # Avoid unnecessary type hint age = 30 # Type is clear without specifying it
Use Expressive Variable Names:
Choose variable names that convey meaning and make type hints redundant.
Example:
def calculate_area(length: float, width: float) -> float: return length * width
Be Consistent with Typing Styles:
Choose a consistent style for type hints, either using the
:
notation or the->
notation for function return types.Example:
# Consistent style with `:` def greet(name: str) -> None: print(f"Hello, {name}!") # Consistent style with `->` def multiply(a: int, b: int) -> int: return a * b
Specific Typing Practices
Type Annotations for Variables:
Use type annotations for variables, especially in cases where the type might not be immediately obvious.
Example:
count: int = 0
Type Annotations for Function Parameters and Return Types:
Clearly annotate the types of function parameters and return types.
Example:
def calculate_total(items: List[float]) -> float: return sum(items)
Type Aliases:
Use typing module aliases to create readable and self-documenting type aliases for complex types.
Example:
from typing import List, Tuple Coordinates = Tuple[float, float] PointList = List[Coordinates] def plot_points(points: PointList) -> None: # Plotting logic here
Union Types:
Use Union types when a variable or parameter can have multiple types.
Example:
from typing import Union def display_value(value: Union[int, float, str]) -> None: print(value)
Type Hinting in Generics:
Use generic types when working with containers or collections.
Example:
from typing import List, Tuple def process_data(data: List[Tuple[str, int]]) -> None: # Processing logic here
Callable Types:
Clearly annotate callable types using Callable from the typing module.
Example:
from typing import Callable def apply_function(func: Callable[[int, int], int], a: int, b: int) -> int: return func(a, b)