Files
telecom-rd-project-template/.agents/skills/telecom-rd-standards/references/source-documents/06-python-coding.md
T
2026-07-28 22:30:20 +08:00

11 KiB
Raw Blame History

中国电信软件研发规范编码规范(Python 分册)

脱敏整理版:已移除编制人员、联系人和联系方式,并合并无意义硬换行。技术条款、章节和示例以原始 DOCX 为争议核验依据。

中国电信软件研发规范编码规范 (Python 分册) (修订版)

中国电信集团有限公司

2023 年 12 月

编制人员信息已移除。

版本变更历史

1 文档说明

1.1 编制说明

为了让不同编码习惯的开发者更好的协作配合, 并且形成良好的基础编码规范与风格, 提高代码安全性 、健壮性 、可读性, 本规范以 PEP8 为基础, 整理了工作中常见的不规范操作, 对 Python 项目开发编码过程进行规范化约束。

1.2 适用范围

本规范适用于指导中国电信软件研发工作。

1.3 起草单位

本规范的起草单位是中国电信集团公司。

1.4 解释权

本规范解释权属于中国电信集团公司。

1.5 版权

本规范的版权属于中国电信集团公司。

1.6 名词解释

PEP 8 约定了 Python 的推荐代码规范, 基于 Guido 和 Barry 的Python 代码风格规范改编而成。

2 Python 开发规范

2.1 命名规范

2.1.1 概述

  1. 【推荐】名字应该能够标识事物的特性, 并且与业务挂钩。

  2. 【推荐】名字应该使用英文单词, 而不能为拼音。

  3. 【推荐】名字可以有两个或三个单词组成, 但不应多于 4 个, 控制在 3至 30 个字母以内。

  4. 【强制】命名不能和关键字冲突。

2.1.2 包和模块命名

  1. 【强制】包命名采用全小写命名。

  2. 【推荐】通过功能命名。

  3. 【推荐】模块命名应短小, 并且全为小写, 如果需要多单词增加可读性,

使用下划线进行拼接。

2.1.3 类命名

  1. 【强制】类命名采用驼峰命名约定, 大写字母开头, 各个单词首字母大写。

  2. 【推荐】 当接口已文档化且主要是用作调用时, 也可以使用函数的命名风格约定。

2.1.4 函数命名

  1. 【推荐】 函数命名都是小写, 必要时使用下划线连接各单词提高可读性。

  2. 【推荐】只有当已有代码风格已经是混合大小写时, 为了保留向后兼容性才使用混合大小写。

  3. 【强制】用单下划线(_)开头表示模块函数是 protected 的。

  4. 【强制】用双下划线(__)开头的实例方法表示类内私有。

2.1.5 变量命名

  1. 【强制】变量名都是小写, 多单词使用下划线连接。

  2. 【推荐】类型变量名称通常应使用简短的驼峰命名, 建议将后缀_co 或_contra 添加到用于声明相应的协变和逆变的行为, 例

如:from typing import TypeVar

VT_co = TypeVar('VT_co' covariant=True)KT_contra = TypeVar('KT_contra' contravariant=True)

  1. 【强制】类型变量的定义统一放在 import 之后。

  2. 【强制】类变量统一放在类注释之后, 所有类函数之前。

  3. 【推荐】全局变量: 适用于函数的命名规范。

  4. 【强制】用单下划线(_)开头表示模块变量是 protected 的。

  5. 【强制】用双下划线(__)开头的实例变量表示类内私有。

2.1.6 常量命名

  1. 【推荐】全部使用大写并且下划线将单词分开。

2.1.7 异常命名

  1. 【推荐】 由于异常实际上也是类, 因此类命名的约定也适用与异常 。不同的是, 如果异常实际上是抛出错误的话, 异常名后应该加上“Error ”的后缀。

2.2 注释规范

2.2.1 概述

  1. 【推荐】一般情况下源程序的有效注释量必须在 30%以上。

  2. 【强制】避免使用装饰性内容, 保持注释的简洁。

  3. 【强制】注释信息不仅要包括代码的功能, 还应给出原因, 不要为注释而注释。

  4. 【强制】注释不能嵌套。

  5. 【强制】避免使用行尾注释。

  6. 【推荐】生成开发文档的需要用中文编写。

  7. 【推荐】如果需要注释的内容太多, 需附加文档进行说明, 注释时加上"参见《 ****》"。

  8. 【强制】复杂的分支流程必须注释。

  9. 【推荐】代码质量不高但能正常运行, 或者还没有实现的代码用# TODO:声明。

  10. 【参考】存在错误隐患的代码用# FIXME:声明。

2.2.2 程序文件注释

  1. 【强制】采用文档字符串的形式进行注释(三个双引号的形式) 。

  2. 【参考】应该包含如下:

文件描述 (Description): 描述此类的作用;# 作者 (Author): 创建者或者修改者名;# 版本 (Version): 创建或者修复时的编号, 需要自行在 bug 管理系统中创建 bug 号, 使用 bug 号进行命名(若无 bug 管理工具的临时办法: 如无 bug 号, 从 1 开始, 修改时依次增加);# 日期(Date): 创建或者修改时的日期, 使用“ - ”进行年月日分割;# 记录(Record): 创建或者修改的工作内容描述;

2.2.3 类注释

  1. 【强制】类应该在其定义下有一个用于描述该类的文档字符串。

  2. 【推荐】如果你的类有公共属性(Attributes), 那么文档中应该有一个属性(Attributes)段, 并且应该遵守和函数参数相同的格式。

2.2.4 函数和方法注释

下文所指的函数,包括函数 、方法 、 以及生成器。

  1. 【强制】一个函数必须要有文档字符串, 除非它满足以下条件之一:

a) 外部不可见

b) 非常短小

c) 简单明了

  1. 【强制】文档字符串应该包含函数做什么, 以及输入和输出的详细描述 。通常不应该描述“ 怎么做 ”, 除非是一些复杂的算法 。 当开发人员调用该函数时, 文档字符串应该提供足够的信息, 而无需看代码 。对于复杂的代码, 在代码旁边加注释会比使用文档字符串更有意义。

  2. 【参考】 关于函数的几个方面应该在特定的小节中进行描述记录, 这几个

方面如下文所述 。每节应该以一个标题行开始. 标题行以冒号结尾 。 除标题行外, 节的其他内容应被缩进 2 个空格。

  1. 【参考】Args:

列出每个参数的名字,并在名字后使用一个冒号和一个空格,分隔对该参数的描述 。如果描述太长超过了单行 80 字符,使用 2 或者 4 个空格的悬挂缩进(与文件其他部分保持一致) 。描述应该包括所需的类型和含义 。如果一个函数接受foo(可变长度参数列表)或者**bar (任意关键字参数),应该详细列出foo 和**bar。

  1. 【参考】Returns: (或者 Yields: 用于生成器)

描述返回值的类型和语义 。如果函数返回 None, 这一部分可以省略。

  1. 【参考】Raises:

列出与接口有关的所有异常。

2.2.5 块注释和行注释

  1. 【强制】块注释一般写在对应的代码之前, 并且和对应的代码有同样的缩进级别。

  2. 【强制】块注释的每一行都应该以#和一个空格开头(除非该文本是在注释内缩进对齐的) 。

  3. 【强制】块注释中的段落应该用只含单个#的一行隔开。

2.2.6 行内注释

  1. 【参考】尽量少用行内注释。

  2. 【参考】行内注释是和代码语句写在一行内的注释 。行内注释应该至少和代码语句之间有两个空格间隔, 并且以#和一个空格开始。

2.3 格式规范

2.3.1 概述

  1. 【强制】代码未写, 文档先行 。注释必须按照统一的范式编写。

  2. 【强制】 关系运算必须常量在左 、变量在右。

  3. 【强制】不许使用复杂的运算表达式, 必要时添加括号而不依赖于优先级。

2.3.2 缩进

  1. 【强制】缩进使用 4 个空格, 空格是首选的缩进方式。

  2. 【强制】禁止混用空格和 Tab。

2.3.3 换行

  1. 【推荐】每行代码的最大长度不该超过 80 个字符, 以下情况除外:

a) 长的导入模块语句

b) 注释里的 URL

2.3.4 空白行

  1. 【强制】使用 2 个空行来分隔最外层的函数(function)和类(class)定义。

  2. 【强制】使用 1 个空行来分隔类中的方法(method)定义。

  3. 【推荐】在函数内使用空行(尽量少) 使代码逻辑更清晰。

2.3.5 对齐

  1. 【强制】不要用空格来垂直对齐多行间的标记, 因为这会成为维护的负担(适用于:, #, =等)。

  2. 【推荐】续行应该与包裹元素对齐, 要么使用圆括号 、方括号 、花括号在

内的隐式行连接来垂直对齐, 要么使用悬挂行缩进对齐。垂直对齐:

2.3.6 库的导入

  1. 【强制】每个导入应该独占一行。

  2. 【强制】使用 import 开头的导入, 一行只能导入一个库, 禁止使用逗号分开导入多个库。

  3. 【推荐】使用from import 形式的导入, 一行只能导入一个库, 特殊情况下可以使用逗号分开导入多个库。

  4. 【强制】导入总应该放在文件顶部, 位于模块注释和文档字符串之后, 模块全局变量和常量之前 。导入应该按照从最通用到最不通用的顺序分组:

a) 标准库的导入

b) 第三方库的导入

c) 应用程序指定导入

  1. 【推荐】推荐使用绝对路径导入, 如果包导入时系统没有正确的配置(比如包里的一个目录在 sys.path 里的路径之后), 使用绝对路径会更具可读性(至少能提供错误信息):

  2. 【强制】 隐式相对 imports 是禁止使用的。

显示导入和隐式导入说明假设有如下包结构:

隐式相对导入, 是禁止使用的import bench# 显式相对导入

from . import bench

  1. 【推荐】显式的相对 imports 也是一种可以接受的方式, 标准库代码应当一直使用绝对 imports, 避免复杂的包布局。

from . import sibling from .sibling import example

2.3.7 字符串

  1. 【强制】避免在循环中用+和+=操作符来累加字符串。

主要原因:1. 字符串是不可变的, 每一次的赋值, 原来引用的对象没有及时被删除(系统有机制回收内存, 但是不及时), 增加内存负担;2. 随着字符串的累加, 长度越来越长, 写入的时间也逐渐增加, 所以如果循环规模比较大, 效率就明显下降。

  1. 【推荐】在同一个文件中, 保持使用字符串引号的一致性 。使用单引号 ’或者双引号"之一用以引用字符串, 并在同一文件中沿用。

2.3.8 空值比较

  1. 【推荐】使用 if foo is None: 形式来比较空值。

2.3.9 表达式和语句中的空格

  1. 【推荐】 以下情况避免无关的空格:

i. 在括号或大括号内

ii. 在尾随逗号和后面的右括号之间

iii. 在逗号, 分号或冒号前面正例:if x == 4: print x y; x y = y x反例:if x == 4 : print x y ; x y = y x

iv. 紧接在开始函数调用的参数列表的开括号之前正例:spam(1)反例:spam (1)

v. 紧接在索引或切片的左中括号之前

vi. 在一个赋值(或其他)运算符前后多于一个空格

  1. 【参考】其他建议

i. 总是围绕这些二元运算符在两侧使用一个空格正例:x = 1 y = 2 long_variable = 3反例:x = 1 y = 2 long_variable = 3

ii. 用于指示关键字参数或默认参数值时, 不要在=符号周围使用空格