#
Coding Style Guide
#
Indentation
Use four spaces for indentation. Do not use TAB
.
#
Strings
# Prefer single quotes for strings
s = 'this is a string'
# Use double quotes only if the string itself contains a single quote
s = "this ' is single quote"
#
Docstrings
Always use triple quotes for docstrings.
def f():
"""This is a multi-line docstring.
Here is some content. Docstrings partially support Markdown.
"""
def g():
"""This is a single-line docstring."""
Use natural language to describe the function's purpose. Do not enumerate each parameter and return value.
# Correct
def add(a: int, b: int):
"""Add two integers `a` and `b`."""
# Incorrect
def add(a: int, b: int):
"""
@param a, the first argument
@param b, the second argument
@return, the result of a + b
"""
#
Spaces
# Add a space after `,` or `:`
a, b = 1, 2
c = [1, 2, 3]
d = {'key': 'value'}
# Spaces may be added around operators
res = 1 + 2
if res < 2: pass
# Spaces can also be selectively added to indicate operator precedence
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
# Add a space after `:` in type annotations
def f(a: int, b: float): ...
def g() -> int: ...
# Add spaces around `=` when specifying default values in function parameters
def f(a: int = 1, b: int | None = None): ...
# However, omit spaces if the parameter has no type annotation
def f(a=1, b=2): pass
# Do not add spaces in keyword arguments when calling functions
print(1, 2, 3, end='', sep=',')
f(a=10, b=20)
#
Naming Conventions
- Classes:
CapitalizedWords
- Functions and variables:
lower_case_with_underscores
- Constants and enums:
UPPER_CASE_WITH_UNDERSCORES
orCapitalizedWords
- Anonymous ordered variables:
_0
,_1
,_2
- Discarded variables:
_
- Some standard library functions:
lowercase
Here are some commonly used naming conventions:
self
: The first parameter of an instance methodcls
: The first parameter of class methods and__new__
#
Using Abbreviations
Use abbreviations only for temporary variables and internal implementations.
Abbreviations should be well-established, include key syllables of the original word, and be immediately recognizable.
context
->ctx
(✔)temporary
->tmp
(✔)distribution
->dist
(✔)visited
->vis
(❌)
# Incorrect: Using abbreviations in public function parameters
def some_pub_fn(ctx, req_id, data):
pass
# Correct
def some_public_function(context, request_id, data):
pass
#
Using Precise Terminology
Naming should convey precise meanings, especially when multiple synonyms exist.
For example, count
, size
, and length
all relate to quantity, but they have different nuances:
count
: Represents a counted valuelength
: Represents the number of elements in a containersize
: Represents the byte size of an object
s = 'aaabc⭐'
count = s.count('a')
length = len(s)
size = len(s.encode())
print(f"{s!r} has a length of {length}, a size of {size} bytes, and contains {count} occurrences of 'a'")
# 'aaabc⭐' has a length of 6, a size of 8 bytes, and contains 3 occurrences of 'a'
#
Using Professional Terminology
- For item quantities in a game:
quantity
is better thanitem_count
- For grid counts:
area
(meaning surface area) is better thangrid_count
#
Avoiding Built-in Names
# Incorrect: Overwriting `builtins.map`
map = [[1, 2, 3], [4, 5, 6]]
# Incorrect: Overwriting `builtins.type`
type = some_thing.type
#
Internal Functions and Classes
Use a single underscore _
as a prefix for internal functions. Never use a double underscore __
(except for magic methods).
def _internal_func():
"""This is an internal function."""
class _InternalClass:
def _internal_f(self): pass
#
Importing Modules
- Import standard library modules first.
- Then import third-party dependencies.
- Finally, import project-specific modules.
from typing import Any
from collections import deque
from array2d import array2d
from ..utils import logger
#
Coding Practices
Use is not
when checking for None
. Do not explicitly compare with True
or False
.
# Correct
if x is not None: pass
# Incorrect
if x != None: pass
# Correct
x = True
if x: pass
if not x: pass
# Incorrect
if x == True: pass
if x is True: pass
if x != False: pass
The if
statement implicitly calls bool()
, so it can be used to check if a container is empty.
not_empty_list = [1]
not_empty_string = '1'
truth = True
if not_empty_list:
print('true value')
if not_empty_string:
print('true value')
if truth:
print('true value')
# Explicitly checking for emptiness is also valid
if len(not_empty_list) > 0: pass
#
References
PEP 8 – Style Guide for Python Code