pocketpy/docs/coding-style-guide.md
blueloveTH 5d428a8818 Create coding-style-guide.md
rename

fix doc link
2025-03-03 18:00:24 +08:00

4.9 KiB
Raw Permalink Blame History

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_UNDERSCORES or CapitalizedWords
  • 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 method
  • cls: 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 value
  • length: Represents the number of elements in a container
  • size: 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 than item_count
  • For grid counts: area (meaning surface area) is better than grid_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

  1. Import standard library modules first.
  2. Then import third-party dependencies.
  3. 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