-
Indentation: Use 4 spaces per indentation level. Continuation lines should align with the opening delimiter or use a hanging indent. Hanging indents should not have arguments on the first line and should further indent to distinguish from the rest.
# Correct: def long_function_name(var_one, var_two, var_three, var_four): print(var_one) # Correct (hanging indent): def long_function_name( var_one, var_two, var_three, var_four): print(var_one) # Wrong: def long_function_name(var_one, var_two, var_three, var_four): print(var_one) -
Tabs or Spaces: Spaces are preferred over tabs for indentation. Mixing tabs and spaces is disallowed.
# Correct: if True: print("Spaces for indentation") # Wrong: if True: β print("Tabs for indentation") -
Maximum Line Length: Limit lines to 79 characters, and 72 characters for comments and docstrings. For teams preferring longer lines, the limit can be extended to 99 characters, provided comments and docstrings are still wrapped at 72 characters.
# Correct: comment = "This is an example within the length limit." # Wrong: long_comment = "This line exceeds the recommended maximum length, which is discouraged." -
Blank Lines: Surround top-level function and class definitions with two blank lines. Use a single blank line to separate method definitions inside a class. Extra blank lines can be used sparingly to separate related code sections.
# Correct: class MyClass: def method(self): pass # Wrong: class MyClass: def method(self): pass -
Source File Encoding: Always use UTF-8 encoding. Non-ASCII characters should be used sparingly, preferably only for human names or specific data.
# Correct: # -*- coding: utf-8 -*- author = "JosΓ©" # Wrong: author = "Jos\351" # Non-UTF-8 encoding
-
Import Format: Imports should be on separate lines. Group imports in the following order: standard library imports, third-party imports, and local imports.
# Correct: import os import sys from flask import Flask from mymodule import myfunction # Wrong: import sys, os -
Absolute Imports: Absolute imports are recommended for clarity and better error handling. Explicit relative imports are acceptable in some cases, particularly in complex package layouts.
# Correct: from mymodule import myfunction # Also Correct (for complex layouts): from .mymodule import myfunction -
Wildcard Imports: Wildcard imports should generally be avoided as they make it unclear which names are present in the namespace.
# Correct: from math import pi # Wrong: from math import * # Wrong: from mymodule import *
- Placement: Module-level βdundersβ (e.g.,
__all__,__author__,__version__) should appear after the module docstring but before any import statements, except forfrom __future__imports.""" This is the example module. """ from __future__ import print_function __all__ = ['foo', 'bar'] __version__ = '1.0' __author__ = 'Your Name' import os
- Consistency: Single and double quotes are equivalent in Python; choose one and stick with it. Use triple double quotes for docstrings to align with PEP 257.
# Correct: name = "John" name = 'John' # Correct (docstring): def foo(): """This is a docstring.""" pass
-
Avoid Extraneous Whitespace: Avoid unnecessary whitespace inside parentheses, brackets, braces, and before commas, colons, or semicolons.
# Correct: spam(ham[1], {eggs: 2}) # Wrong: spam( ham[ 1 ], { eggs: 2 } ) -
Binary Operators: Surround binary operators with a single space on both sides, except when used for alignment.
# Correct: x = 1 + 2 # Wrong: x=1+2 -
Spacing for Matrix Brackets: In slices, treat colons as binary operators, with equal spacing on either side. In extended slices with omitted parameters, omit the space around colons:
# Correct: ham[1:9], ham[1:9:3] # Wrong: ham[1: 9], ham[1 :9] -
Function Calls and Indexing: Do not add space immediately before the open parenthesis that starts the argument list of a function call or indexing/slicing:
# Correct: spam(1) dct['key'] = lst[index] # Wrong: spam (1) dct ['key'] = lst [index] -
Assignment Operators: Use a single space around assignment operators (
=) for assignments, except when aligning multiple assignments to improve readability:# Correct: x = 1 y = 2 # Wrong: x = 1 y = 2
-
Block Comments: Use block comments to explain sections of code, formatted as complete sentences. Each line of a block comment starts with a
#and a single space.# Correct: # This block comment explains the following code section. x = x + 1 # Wrong: #This block comment is not properly formatted. x = x + 1 -
Inline Comments: Use inline comments sparingly, separating them from the code by at least two spaces. They should not state the obvious.
# Correct: x = x + 1 # Increment x # Wrong: x = x + 1 #Increment x # Wrong (obvious): x = x + 1 # Add one to x -
Documentation Strings: Follow PEP 257 for docstring conventions. Write docstrings for all public modules, functions, classes, and methods. Multiline docstrings should have the closing
"""on a line by itself.# Correct: def foo(): """ This is a multiline docstring. It describes the function's purpose. """ pass # Wrong: def foo(): """This is a one-line docstring.""" pass
-
Descriptive Names: Choose descriptive names that convey the purpose of the variable, function, or class.
# Correct: def calculate_area(radius): pass # Wrong: def foo(x): pass -
Case Styles: Use
lower_case_with_underscoresfor functions and variables,CapWords(CamelCase) for classes, andUPPER_CASE_WITH_UNDERSCORESfor constants.# Correct: def my_function(): my_variable = 10 class MyClass: pass MAX_OVERFLOW = 100 -
Underscores: Use a single leading underscore for non-public methods and instance variables. Use double leading underscores to invoke name mangling for attributes intended to be private in subclasses.
# Correct: class MyClass: def _private_method(self): pass class MyClass: def __private_method(self): pass
-
Comparison Operators: Use
isoris notfor comparisons toNone, andisinstance()for type checks.# Correct: if obj is None: pass if isinstance(obj, int): pass # Wrong: if obj == None: pass if type(obj) is int: pass -
Boolean Values: Do not compare boolean values to
TrueorFalseusing==:# Correct: if greeting: pass # Wrong: if greeting == True: pass -
Return Statements: Be consistent with return statements within a function. If a function returns a value in some cases, ensure all paths return a value, explicitly using
return Nonewhen necessary.# Correct: def foo(x): if x >= 0: return x return None # Wrong: def foo(x): if x >= 0: return x -
Lambda Expressions: Prefer
defoverlambdafor function definitions, as it provides better readability and debugging information.# Correct: def add(x, y): return x + y # Wrong: add = lambda x, y: x + y
-
Exception Handling: Catch specific exceptions rather than using a bare
except:clause. Use exception chaining appropriately withraise X from Y.# Correct: try: result = x / y except ZeroDivisionError: print("Division by zero is not allowed.") raise # Correct (chaining): try: value = some_function() except ValueError as e: raise CustomError("An error occurred") from e # Wrong: try: result = x / y except: print("An error occurred.") -
Context Managers: Use
withstatements for managing resources to ensure proper cleanup.# Correct: with open('file.txt', 'r') as file: content = file.read() # Wrong: file = open('file.txt', 'r') try: content = file.read() finally: file.close() -
Function Annotations: Follow PEP 484 for function annotations. Use PEP 526 for variable annotations, ensuring proper spacing around colons and equal signs:
# Correct: def munge(input: AnyStr = None): pass code: int = 123 # Wrong: def munge(input:AnyStr=None): pass code:int = 123
-
Public vs. Non-Public: Distinguish between public and non-public attributes in classes. Public attributes should be accessible and stable, while non-public attributes are subject to change and should be marked with leading underscores.
# Correct: class MyClass: def public_method(self): pass def _non_public_method(self): pass -
Name Mangling: Use double leading underscores to avoid name clashes in subclasses, though be cautious of potential drawbacks in debugging and introspection.
# Correct: class MyClass: def __private_method(self): pass class SubClass(MyClass): def __private_method(self): pass # This will not override MyClass's __private_method
-
Public Interfaces: Documented interfaces are considered public unless explicitly marked otherwise. Use the
__all__attribute to define the public API of a module.# Correct: __all__ = ['public_function', 'PublicClass'] def public_function(): pass class PublicClass: pass def _internal_function(): pass -
Internal Interfaces: Prefix internal names with a single leading underscore to indicate that they are not part of the public API.
# Correct: _internal_variable = 42 def _internal_function(): pass -
Imported Names: Imported names should be considered an implementation detail. Other modules should not rely on indirect access to such names unless they are explicitly documented as part of the public API.
# Correct: from mymodule import _internal_function # Usage only within the module that imported it: _internal_function()
-
String Methods: Use
.startswith()and.endswith()instead of slicing for checking prefixes or suffixes.# Correct: if filename.startswith('file_'): pass # Wrong: if filename[:5] == 'file_': pass -
Type Comparisons: Use
isinstance()for type comparisons rather than comparing types directly:# Correct: if isinstance(obj, int): pass # Wrong: if type(obj) is int: pass -
Sequences: For sequences (strings, lists, tuples), use the fact that empty sequences are false:
# Correct: if not seq: pass # Wrong: if len(seq) == 0: pass -
Avoid Trailing Whitespace: Avoid trailing whitespace as it can be confusing and lead to subtle bugs.
# Correct: message = "Hello, World!" # Wrong (note the trailing space after the exclamation point): message = "Hello, World! " -
Return in Finally Blocks: Avoid using
return,break, orcontinuein afinallyblock as it can interfere with exception propagation.# Wrong: def foo(): try: return 1 finally: return 2 # This will override the previous return -
Consistent Returns: Be consistent in the use of
returnstatements; if anyreturnin a function returns a value, all should, andreturn Noneshould be explicit when no value is returned.# Correct: def foo(x): if x >= 0: return x return None # Wrong: def foo(x): if x >= 0: return x -
Use of Annotations: Follow PEP 484 for function and variable annotations. Variable annotations should have proper spacing around colons and equal signs, consistent with the style guide.
# Correct: def add(a: int, b: int) -> int: return a + b x: int = 10 # Wrong: def add(a:int,b:int)->int: return a + b x:int=10