1.5 Python Code Style Conventions(整理版)
原始笔记:Coding-conventions.md 原始教程:1.5 Python Code Style Conventions created: 2026-07-25 12:16 整理说明:本版本只围绕原笔记已有的 PEP 8、缩进、行宽、空行、空格、命名、注释和 docstring 进行整理和补充。
内容简要概括
Python coding conventions 通过统一代码布局和命名方式提高可读性与可维护性。PEP 8 对缩进、换行、空行、空格和命名提供了常用约定,而注释与 docstring 应解释代码意图和接口。实际项目应以团队规范为准,并在同一代码库中保持一致。
PEP 8、coding conventions、缩进、行宽、空行、空格、snake_case、PascalCase、命名规范、block comment、inline comment、docstring、Google style
目录
1. PEP 8 与缩进
PEP 8 是 Python 常用的代码风格指南。每一级缩进使用 4 个空格:第一层 4 个空格,第二层 8 个空格,依此类推。
悬挂缩进
当函数调用或其他括号表达式较长时,可以让第一行只写到左括号,后续内容统一多缩进一级:
foo = long_function_name(
var_one,
var_two,
var_three,
var_four,
)
函数定义
函数定义中的长参数列表采用相同方式:
def long_function_name(
var_one,
var_two,
var_three,
var_four,
):
print(var_one)
右括号与语句起始位置对齐,使表达式边界清晰。
2. 行宽与表达式换行
最大行宽
原笔记采用的约定是:普通代码行不超过 80 个字符,注释或 docstring 不超过 73 个字符。团队也可以采用不同的限制,但应在项目内保持一致。
表达式过长时,推荐用成对的括号包裹并自动续行,不推荐使用反斜杠 \。下面的格式可以作为默认规范:
if (
first_condition
and second_condition
):
do_something()
列表、函数调用和复杂表达式也采用同样原则:左括号后换行,内容缩进一级,右括号与语句起始位置对齐。
二元运算符的位置
长表达式拆成多行时,把二元运算符放在下一行开头,而不是上一行末尾。
推荐:
income = (
gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest
)
不推荐:
income = (
gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest
)
运算符位于行首时更容易与右侧操作数对应,也能让各行的运算结构保持对齐。
3. 空行
顶层函数和类之间空两行
“顶层”指直接定义在 Python 模块中、不属于其他类或函数的定义。
import math
def calculate_area(radius):
return math.pi * radius**2
class Circle:
pass
def calculate_diameter(radius):
return radius * 2
在这个例子中:
import与第一个顶层定义之间有两行空行;- 顶层函数与类之间有两行空行;
- 两个顶层函数之间也应空两行。
不同导入组之间通常保留一行空行,例如标准库导入与项目内部导入:
import argparse
from inflammation import models, views
类中的方法之间空一行
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius**2
def diameter(self):
return self.radius * 2
类中的方法属于同一个类,关系更紧密,因此只空一行。
函数内部少量使用空行
函数内部的空行可用于划分逻辑阶段:
def process_records(records):
valid_records = [
record for record in records
if record.is_valid()
]
sorted_records = sorted(
valid_records,
key=lambda record: record.timestamp,
)
return generate_report(sorted_records)
简单函数不需要为了形式增加空行:
def add_numbers(a, b):
result = a + b
return result
装饰器与定义之间不要空行
装饰器直接作用于紧随其后的定义,两者之间不应插入空行:
@app.route("/users")
def get_users():
return users
4. 空格
括号内部不加无意义空格
推荐:
my_function(colour[1], {id: 2})
不推荐:
my_function( colour[ 1 ], { id: 2 } )
逗号、分号和冒号前不留空格
推荐:
print(x, y)
mapping = {"name": "Alice"}
不推荐:
print(x , y)
mapping = {"name" : "Alice"}
一般规律是:标点前无空格,标点后通常保留一个空格。
切片中的冒号
简单切片不加空格:
values[1:5]
values[:5]
values[1:]
matrix[:, 1]
复杂切片中,冒号可以近似看作低优先级二元运算符,两侧保持相同数量的空格:
values[start + offset : stop + offset]
不要只在一侧加空格:
values[start + offset: stop + offset] # 不对称
二元运算符
二元运算符两侧通常各保留一个空格。
赋值运算符:
x = 1
增强赋值:
x += 1
total -= discount
比较运算符:
x == 1
x != 1
x <= 10
成员运算符:
item in collection
item not in collection
身份运算符:
value is None
value is not None
布尔运算符:
condition_a and condition_b
condition_a or condition_b
not condition_a
普通赋值中的 =
普通赋值的 = 两侧各保留一个空格:
axis = "x"
angle = 90
size = 450
这里的 = 表示执行赋值。
关键字参数中的 =
函数调用中的关键字参数不在 = 两侧加空格:
my_function(
1,
2,
axis=axis,
angle=angle,
size=size,
name=name,
)
axis=axis 表示把右侧变量 axis 的值传给名为 axis 的参数。
推荐:
draw(size=450, angle=90)
不推荐:
draw(size = 450, angle = 90)
默认参数中的 =
没有类型注解的默认参数不在 = 两侧加空格:
def draw(size=450, angle=90):
pass
参数包含类型注解时,在默认值的 = 两侧加空格:
def draw(size: int = 450, angle: int = 90):
pass
对比:
def draw(size=450): # 无类型注解
pass
def draw(size: int = 450): # 有类型注解
pass
5. 命名规范
命名应表达对象的职责,并在同一项目中使用一致的风格。
变量:snake_case
变量名应说明它存储的具体内容:
patient_name = "Alice"
temperature_readings = [36.5, 37.1]
number_of_records = 20
函数和方法:snake_case
函数名通常使用动词,说明它执行的操作:
calculate_average()
load_patient_records()
validate_user_input()
send_email()
类:PascalCase
类通常表示一种对象或概念,因此一般使用名词:
class PatientRecord:
pass
class TemperatureAnalyzer:
pass
class HTTPServerError(Exception):
pass
模块:简短、全小写
Python 文件名也是模块名:
models.py
analysis.py
data_loader.py
temperature_utils.py
可以使用下划线提高可读性:
data_processing.py
不推荐:
DataProcessing.py
patient-records.py
VeryLongModuleForProcessingPatientData.py
模块名不能使用连字符 -,因为它会被解释为减号,无法正常导入:
import data-processing # 错误
包:简短、全小写
包是包含多个模块的目录:
inflammation/
datatools/
analytics/
PEP 8 对包名更倾向于简短、连续的小写形式:
datatools
而不是:
data_tools
实际项目中带下划线的包名也很常见,应优先遵循项目现有规范。
命名速查
| 对象 | 推荐风格 | 示例 |
|---|---|---|
| 变量 | snake_case |
patient_name |
| 函数、方法 | snake_case |
calculate_mean() |
| 常量 | UPPER_CASE |
MAX_RETRIES |
| 类 | PascalCase |
PatientRecord |
| 异常类 | PascalCase |
InvalidDataError |
| 模块 | 全小写,可加下划线 | data_loader.py |
| 包 | 简短全小写 | datatools |
6. 注释
注释应解释代码中不明显的意图或约束,而不是重复代码本身已经清楚表达的信息。
Block comment:块注释
块注释用于解释它后面的一段代码,并与这段代码保持相同缩进。格式要求:
- 每行以
#开头; #后有一个空格;- 写成完整句子;
- 与所描述的代码处于相同缩进层级。
def calculate_discount(user):
# Premium users receive the historical discount rate to
# preserve compatibility with existing subscriptions.
discount_rate = 0.2 if user.is_premium else 0.1
return discount_rate
Inline comment:行内注释
行内注释放在语句末尾。代码和注释之间至少保留两个空格,并谨慎使用:
retry_count += 1 # The first attempt is numbered zero.
行内注释适合解释非常局部、简短且不明显的特殊情况。
7. Docstring
Docstring 用于说明模块、类或函数的接口。原笔记采用 Google style:
def fibonacci(n):
"""Calculate the nth Fibonacci number.
Args:
n: Index of the Fibonacci number.
Returns:
The nth Fibonacci number.
Raises:
ValueError: If n is negative.
"""
该结构分别说明参数、返回值和可能抛出的异常,便于读者理解函数的使用约定。