4.9 KiB
| icon | order | label |
|---|---|---|
| book | -5 | 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_UNDERSCORESorCapitalizedWords - 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:
quantityis 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