Writing clean code in Python involves adhering to best practices that make your code readable, maintainable, and efficient. Here are some key principles and practices to help you write clean Python code:
1. Follow PEP 8
PEP 8 is the style guide for Python code. It covers a wide range of topics from naming conventions to indentation. Here are some highlights:
- Indentation: Use 4 spaces per indentation level.
- Maximum Line Length: Limit all lines to a maximum of 79 characters.
- Blank Lines: Use blank lines to separate top-level function and class definitions, and methods within classes.
- Imports: Group imports in the following order:
- Standard library imports.
- Related third-party imports.
- Local application/library-specific imports.
- Naming Conventions:
- Function names should be lowercase, with words separated by underscores (snake_case).
- Variable names should be lowercase, with words separated by underscores (snake_case).
- Class names should use the CamelCase convention.
2. Write Meaningful Names
Choose descriptive and unambiguous names for variables, functions, classes, and modules.
# Bad a = 10 # Good timeout_seconds = 10
3. Keep Functions Small and Focused
A function should do one thing and do it well. If a function is too long or does multiple things, consider breaking it into smaller functions.
# Bad def process_data(data): # Process data clean_data = clean(data) # Analyze data result = analyze(clean_data) return result # Good def process_data(data): clean_data = clean(data) return analyze(clean_data) def clean(data): # Cleaning logic pass def analyze(clean_data): # Analysis logic pass
4. Use List Comprehensions and Generator Expressions
List comprehensions and generator expressions are concise and readable.
# Bad squares = [] for x in range(10): squares.append(x**2) # Good squares = [x**2 for x in range(10)]
5. Handle Exceptions Properly
Use exceptions to handle errors and exceptional cases. Avoid using exceptions for control flow.
# Bad try: value = my_dict[key] except KeyError: value = default_value # Good value = my_dict.get(key, default_value)
6. Use Docstrings
Write docstrings for all public modules, functions, classes, and methods. This helps others (and yourself) understand what your code does.
def add(a, b): """ Add two numbers and return the result. Parameters: a (int or float): The first number. b (int or float): The second number. Returns: int or float: The sum of the two numbers. """ return a + b
7. Avoid Global Variables
Global variables can lead to code that is difficult to debug and understand. Prefer local variables and function parameters.
8. Use Libraries and Built-in Functions
Leverage Python's standard library and built-in functions to write concise and efficient code.
# Bad result = [] for item in items: result.append(item.upper()) # Good result = list(map(str.upper, items))
9. Write Tests
Writing tests ensures that your code works as expected and helps prevent bugs.
import unittest def add(a, b): return a + b class TestMathFunctions(unittest.TestCase): def test_add(self): self.assertEqual(add(1, 2), 3) self.assertEqual(add(-1, 1), 0) self.assertEqual(add(-1, -1), -2) if __name__ == '__main__': unittest.main()
10. Refactor Regularly
Regularly refactor your code to improve readability and maintainability. This involves renaming variables, breaking down large functions, and simplifying complex logic.
Example of Clean Code
Here is an example of a clean Python function that adheres to these principles:
import math from typing import List def calculate_distances(points: List[tuple], origin: tuple = (0, 0)) -> List[float]: """ Calculate the Euclidean distances of a list of points from a given origin. Parameters: points (List[tuple]): A list of tuples representing points (x, y). origin (tuple): A tuple representing the origin point (default is (0, 0)). Returns: List[float]: A list of distances of the points from the origin. """ return [math.sqrt((x - origin[0])**2 + (y - origin[1])**2) for x, y in points] # Example usage points = [(1, 2), (3, 4), (5, 6)] distances = calculate_distances(points) print(distances) # Output: [2.23606797749979, 5.0, 7.810249675906654]