1. 通用原则

  • 总体规范参考 Google 规范,略有改动 详见 $\rightarrow$ https://google.github.io/styleguide/pyguide.html

  • 使用或借助 AI 写代码请务必自己理解每个代码都在干什么

  • 行宽不超过 80 字符,设置 vscode 行宽 80 字符线:

    1. Ctrl(Cmd) + , 或者 File $\rightarrow$ Preferences $\rightarrow$ Settings
    2. 搜索:ruler 编辑 settings.json:
1{
2  "editor.rulers": [80] // 原有配置的基础上添加这一行
3}
  • 代码可读性第一,避免过度优化或炫技

  • 变量、函数、类名应自解释,避免无意义缩写(如 a, tmp1),除非是广泛接受的缩写(如 id, url, cmd)

  • 错误处理必须显式,不能忽略可能的异常、错误码或返回值

  • 全英文注释:统一,正式,美观,且标点只使用半角标点(英文字符)

    1. 标点(: , ; . ? !)前不加空格,后加一个空格,
      () [] {} "" '')外侧加空格内测不加
      - _)前后不加空格,其余所有运算符前后都有空格
    2. 在函数名和左括号之间不要留空格。在参数列表的逗号后留一个空格。 int add(a, b);
    3. 避免在圆括号、方括号或花括号内部紧邻留空格。 list[1:5] dict = {'key': value}
  • 声明与初始化尽可能的靠近,如

1int i = function();
  • 设置pylance:

    1. Ctrl(Cmd) + , 或者 File $\rightarrow$ Preferences $\rightarrow$ Settings
    2. 搜索:typeCheckingMode 设置为基础(basic)及以上(当然越高越好)
  • 以下标准可以存在极少的例外

2. Python

2.1 文件与模块

1import os
2import sys                             # 标准库
3
4import numpy as np
5from scipy import signal               # 第三方库
6
7from utils.logger import setup_logger  # 内部/项目依赖
8
9MAX_CONNECTIONS = 100                  # 模块级常量

2.2 命名规范

类型规则示例
文件小写 + 下划线my_useful_class.py
类、结构体、枚举、类型别名单词首字母大写ProcessData, MaxVelocity
函数、方法小写 + 下划线do_some_thing()
常量全大写 + 下划线A_INT_ABC
类成员全小写且结尾加下划线name*, user_count*

2.3 格式与缩进

缩进两空格而非四空格

1def calculate_velocity(distance: float, time: float) -> float:
2  if time <= 0:
3    raise ValueError("Time must be positive")
4  return distance / time

2.4 类型提示(强烈推荐)

  • 所有公共函数参数和返回值应加类型注解,使用 typing 模块处理复杂类型
 1from typing import Any, Optional, Union, List, Dict, Tuple
 2
 3def process_user_data(
 4  user_id: int,
 5  username: str,
 6  is_active: bool = True,
 7  tags: Optional[List[str]] = None,
 8  metadata: Optional[Dict[str, Any]] = None
 9) -> Dict[str, Any]:
10  """处理用户数据"""
11  if tags is None:
12    tags = []
13  return {'user_id': user_id, 'tags': tags}

2.5 异常处理

禁止裸 except

 1# 明确的异常处理
 2def read_config_file(filepath: str) -> dict:
 3  try:
 4    with open(filepath, 'r') as f:
 5      return json.load(f)
 6  except FileNotFoundError:
 7    logging.error(f"配置文件不存在: {filepath}")
 8    raise
 9  except json.JSONDecodeError as e:  # 明确异常
10    logging.error(f"配置文件格式错误: {e}")
11    raise ValueError("无效的配置文件格式") from e

2.6 注释与文档字符串

2.6.1 模块文档字符串

1"""
2提供用于处理用户账户和权限相关操作的工具函数和类。
3
4该模块封装了与身份验证、会话管理和数据库交互相关的功能。
5主要包含 User 类和 AuthManager 类。
6"""
7import os
8import datetime
9# ... 代码继续

2.6.2 类文档字符串

 1class UserAccount:
 2    """
 3    表示一个用户的账户信息。
 4
 5    负责存储用户的ID、姓名和电子邮件,并提供密码验证方法。
 6
 7    Attributes:
 8        user_id (int): 数据库中用户的唯一标识符。
 9        username (str): 用户的公开用户名。
10        email (str): 用户的注册电子邮件地址。
11    """
12    def __init__(self, user_id, username, email):
13        """初始化 UserAccount 实例。"""
14        self.user_id = user_id
15        self.username = username
16        self.email = email
17    
18    # ... 其他方法

2.6.3 函数/方法文档字符串

 1def calculate_area(length: float, width: float) -> float:
 2    """
 3    计算给定长方形的面积。
 4
 5    如果任一维度为非正数,函数将返回 0.0。
 6
 7    Args:
 8        length (float): 长方形的长度,必须大于或等于 0。
 9        width (float): 长方形的宽度,必须大于或等于 0。
10
11    Returns:
12        float: 长方形的面积 (length * width)。
13
14    Raises:
15        TypeError: 如果 length 或 width 不是数字类型。
16
17    Example:
18        >>> calculate_area(5.0, 4.0)
19        20.0
20    """
21    if not isinstance(length, (int, float)) or not isinstance(width, (int, float)):
22        raise TypeError("长度和宽度必须是数字类型")
23        
24    if length <= 0 or width <= 0:
25        return 0.0
26    
27    return length * width

2.6.4 行内注释

1def complex_algorithm(data: list[float]) -> float:
2  """实现复杂的数值计算算法。"""
3
4  # 预处理:移除异常值(超过3个标准差
5  code...

3. 范式

  • 注意:实际编辑的时候请使用英文注释

  • 范式内包含很多无意义注释(为了理解规范),实际编辑时不要添加

3.1 文件树

1.
2├── main.py
3└── user_management/
4    ├── __init__.py
5    └── user.py

3.2 main.py

 1# main.py
 2import sys                               # Standard library
 3import logging
 4from typing import List, Tuple, Dict, Any
 5
 6from user_management import user           # Internal/project dependencies
 7
 8# Configure logging
 9logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
10
11# Constant naming: ALL_CAPS + underscore
12DEFAULT_USER_ID = 1001
13
14def main():
15  """Main function to demonstrate user data operations."""
16
17  # Indent with two spaces
18  username = "JaneDoe"
19  age = 35
20
21  # Type hints (strongly recommended)
22  is_valid: bool
23  validation_errors: List[str]
24
25  # Call function and unpack tuple
26  is_valid, validation_errors = user.validate_user_data(username, age)
27
28  if is_valid:
29    # Add one space after punctuation
30    logging.info("Validation successful: Creating user.")
31
32    # Declaration and initialization are close
33    new_user = user.User(username, age, DEFAULT_USER_ID)
34
35    # Class member access: name_
36    logging.info(f"User created: {new_user.name_}, ID: {new_user.user_id_}")
37
38    # Demonstrate exception handling
39    try:
40      config_data: Dict[str, Any] = user.load_config_data(
41        "non_existent_config.json"
42      )
43      print(config_data)
44    except FileNotFoundError:
45      logging.warning("Handled expected FileNotFoundError.")
46    except ValueError as e:
47      logging.error(f"Handled Value Error: {e}")
48
49  else:
50    # No space before punctuation
51    logging.error("Validation failed. Errors:")
52    for error in validation_errors:
53      logging.error(f"- {error}")
54
55if __name__ == "__main__":
56  main()

3.3 user_management/user.py

  1"""User data management module.
  2
  3This module provides functions and classes for creating, validating,
  4storing, and retrieving user data.
  5
  6Components:
  71. User class: Represents a system user.
  82. UserManager class: Manages a collection of users (if implemented).
  9"""
 10import json
 11import logging
 12from typing import Any, Optional, List, Dict, Tuple
 13
 14# Module-level constants: ALL_CAPS + underscore
 15MAX_AGE_LIMIT = 150
 16MIN_NAME_LENGTH = 2
 17
 18# Class/Struct naming: PascalCase (CapitalizedWords)
 19class User:
 20  """Represents a system user.
 21
 22  Responsible for storing basic user information and initialization.
 23
 24  Attributes:
 25    user_id_ (int): User's unique ID (lowercase + trailing underscore).
 26    name_ (str): User's name.
 27    age_ (int): User's age.
 28  """
 29
 30  def __init__(self, name: str, age: int, user_id: int) -> None:
 31    """Initializes the User instance.
 32
 33    Args:
 34      name: The user's name.
 35      age: The user's age.
 36      user_id: The user's unique ID.
 37
 38    Raises:
 39      ValueError: When age or user_id is negative.
 40    """
 41    if age < 0 or user_id < 0:
 42      # Error handling must be explicit
 43      raise ValueError("Age and user_id must be non-negative.")
 44
 45    # Declaration and initialization are close
 46    self.user_id_ = user_id
 47    self.name_ = name
 48    self.age_ = age
 49
 50# Function/Method naming: lowercase + underscore
 51def validate_user_data(
 52  name: str,
 53  age: int,
 54  email: Optional[str] = None
 55) -> Tuple[bool, List[str]]:
 56  """Validates user input data.
 57
 58  Checks the format and validity of username, age, and email.
 59
 60  Args:
 61    name: Username. Must be non-empty and 
 62          between MIN_NAME_LENGTH and 50 chars.
 63    age: Age. Must be between 0 and MAX_AGE_LIMIT.
 64    email: Email address. Optional, but must be valid if provided.
 65
 66  Returns:
 67    A tuple containing the validation result: (is_valid, error_messages_list)
 68  """
 69  errors: List[str] = []
 70
 71  # Username validation (spaces around operators)
 72  if not MIN_NAME_LENGTH <= len(name) <= 50:
 73    errors.append("Username length must be between 2 and 50 characters.")
 74
 75  # Age validation
 76  if not 0 <= age <= MAX_AGE_LIMIT:
 77    errors.append(f"Age must be between 0 and {MAX_AGE_LIMIT}.")
 78
 79  # Return boolean and error list
 80  return len(errors) == 0, errors
 81
 82
 83def load_config_data(filepath: str) -> Dict[str, Any]:
 84  """Load configuration data from a JSON file.
 85
 86  Args:
 87    filepath: The path to the configuration JSON file.
 88
 89  Returns:
 90    The configuration data as a dictionary.
 91
 92  Raises:
 93    FileNotFoundError: If the specified file does not exist.
 94    ValueError: If the file content is not valid JSON.
 95  """
 96  try:
 97    with open(filepath, 'r') as f:
 98      return json.load(f)
 99  except FileNotFoundError:
100    # Use logging module instead of print() for debugging
101    logging.error(f"Configuration file not found: {filepath}")
102    raise
103  except json.JSONDecodeError as e:  # Handle specific exceptions, no bare except
104    logging.error(f"Configuration file format error: {e}")
105    raise ValueError("Invalid configuration file format.") from e