04 - 代码规范¶
学习时间: 2-3小时 重要性: ⭐⭐⭐⭐ 让代码更专业
🎯 学习目标¶
- 理解代码规范的重要性
- 掌握PEP 8规范的核心内容
- 学会使用代码格式化工具
- 配置pre-commit钩子
- 建立良好的代码风格习惯
1. 为什么需要代码规范?¶
代码规范的价值¶
Python
# ❌ 不规范的代码 - 难以阅读和维护
def calc(a,b,c):
d=a+b
if c!=0:
return d/c
else:
return None
# ✅ 规范的代码 - 清晰易懂
def calculate_average(num1: float, num2: float, divisor: float) -> float | None:
"""
计算两个数的平均值后除以divisor。
Args:
num1: 第一个数字
num2: 第二个数字
divisor: 除数
Returns:
计算结果,如果divisor为0则返回None
"""
total = num1 + num2
if divisor == 0:
return None
return total / divisor
好处: - ✅ 提高代码可读性 - ✅ 便于团队协作 - ✅ 减少bug - ✅ 方便代码审查 - ✅ 提升专业形象
2. PEP 8规范详解¶
2.1 缩进和空格¶
Python
# ✅ 使用4个空格缩进(不要用Tab)
def my_function():
if True:
print("正确缩进")
# ✅ 运算符两侧加空格
x = 1 + 2
y = (a + b) * (c - d)
# ✅ 逗号后加空格
my_list = [1, 2, 3, 4]
my_dict = {'key': 'value', 'key2': 'value2'}
# ✅ 函数参数默认值两侧不加空格
def greet(name, greeting='Hello'):
pass
# ❌ 错误示例
def bad_function( ):
x=1+2 # 运算符两侧没有空格
my_list=[1,2,3] # 逗号后没有空格
2.2 命名规范¶
Python
# 变量名 - 小写,下划线分隔
user_name = '张三'
max_value = 100
is_valid = True
# 常量 - 全大写,下划线分隔
MAX_SIZE = 100
PI = 3.14159
DEFAULT_TIMEOUT = 30
# 函数名 - 小写,下划线分隔
def calculate_total():
pass
def get_user_info():
pass
# 类名 - 驼峰命名法
class UserProfile:
pass
class DataProcessor:
pass
# 私有变量/函数 - 下划线前缀
_private_var = 10
def _internal_function():
pass
# 强私有 - 双下划线前缀(会触发名称修饰)
class MyClass:
def __init__(self):
self.__very_private = 42
2.3 行长度和换行¶
Python
# ✅ 每行不超过79个字符(现在通常放宽到88或100)
# 长参数列表换行
def my_function(
parameter_one,
parameter_two,
parameter_three,
parameter_four
):
pass
# 长表达式换行
result = (some_long_variable_name
+ another_long_variable_name
- yet_another_variable)
# 使用括号隐式换行
my_list = [
'item_one',
'item_two',
'item_three',
'item_four',
]
# 字符串换行
long_string = (
"这是一个很长的字符串,"
"需要分成多行来写。"
)
2.4 空行¶
Python
# 顶级函数和类之间用2个空行
def function_one():
pass
def function_two():
pass
class MyClass:
# 类内部方法之间用1个空行
def method_one(self):
pass
def method_two(self):
pass
# 函数内部逻辑分组可以用空行
def process_data():
# 数据加载
data = load_data()
# 数据清洗
cleaned_data = clean_data(data)
# 数据分析
results = analyze(cleaned_data)
return results
2.5 导入规范¶
Python
# ✅ 导入顺序:标准库 -> 第三方库 -> 本地模块
# 标准库
import os
import sys
from datetime import datetime
# 第三方库
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# 本地模块
from mypackage import utils
from mypackage.models import MyModel
# ✅ 避免使用通配符导入
# ❌ from module import *
# ✅ 避免循环导入
# 如果必须,使用局部导入
2.6 注释和文档字符串¶
Python
# 行注释 - # 后加1个空格
x = x + 1 # 补偿边界
# 文档字符串(Docstrings)
def calculate_area(length: float, width: float) -> float:
"""
计算矩形的面积。
这是一个更详细的描述,可以包含多行。
解释函数的用途、参数、返回值等。
Args:
length: 矩形的长度
width: 矩形的宽度
Returns:
矩形的面积
Raises:
ValueError: 如果length或width为负数
Examples:
>>> calculate_area(5, 3)
15.0
"""
if length < 0 or width < 0:
raise ValueError("长度和宽度必须为非负数")
return length * width
class Calculator:
"""
一个简单的计算器类。
支持基本的数学运算。
Attributes:
history: 存储计算历史
"""
def __init__(self):
"""初始化计算器。"""
self.history = []
3. 代码格式化工具¶
3.1 Black¶
Black是Python社区广泛使用的代码格式化工具,号称"不妥协的代码格式化工具"。
Bash
# 安装
pip install black
# 格式化单个文件
black my_script.py
# 格式化整个目录
black my_project/
# 检查格式(不修改文件)
black --check my_script.py
# 显示差异
black --diff my_script.py
# 使用特定行长度(默认88)
black --line-length 100 my_script.py
Black配置(pyproject.toml):
TOML
[tool.black]
line-length = 88
target-version = ['py311']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| build
| dist
)/
'''
3.2 isort¶
isort用于自动排序和组织import语句。
Bash
# 安装
pip install isort
# 格式化文件
isort my_script.py
# 检查格式
isort --check-only my_script.py
# 显示差异
isort --diff my_script.py
isort配置(pyproject.toml):
TOML
[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88
known_first_party = ["mypackage"]
3.3 autopep8¶
autopep8是另一个PEP 8格式化工具。
Bash
# 安装
pip install autopep8
# 格式化文件
autopep8 --in-place my_script.py
# 只修复特定问题
autopep8 --select=E101,W191 --in-place my_script.py
# 递归格式化
autopep8 --in-place --recursive my_project/
4. 代码质量检查工具¶
4.1 flake8¶
flake8是一个轻量级的代码风格检查工具。
Bash
# 安装
pip install flake8
# 检查文件
flake8 my_script.py
# 检查目录
flake8 my_project/
# 忽略特定错误
flake8 --ignore=E501,W503 my_script.py
# 设置最大行长度
flake8 --max-line-length=100 my_script.py
flake8配置(setup.cfg):
INI
[flake8]
max-line-length = 88
extend-ignore = E203, W503
exclude =
.git,
__pycache__,
build,
dist,
.venv
4.2 pylint¶
pylint是一个更全面的代码质量检查工具。
Bash
# 安装
pip install pylint
# 检查文件
pylint my_script.py
# 生成报告
pylint --reports=y my_project/
# 禁用特定检查
pylint --disable=C0103 my_script.py
pylint配置(.pylintrc):
INI
[MASTER]
max-line-length=88
disable=
C0103, # 命名规范
R0903, # 类方法太少
R0913 # 参数太多
[FORMAT]
good-names=i,j,k,ex,Run,_,logger
4.3 mypy¶
mypy是Python的静态类型检查工具。
Bash
# 安装
pip install mypy
# 检查文件
mypy my_script.py
# 检查目录
mypy my_project/
# 严格模式
mypy --strict my_script.py
5. pre-commit配置¶
pre-commit可以在提交代码前自动运行检查和格式化。
5.1 安装和配置¶
.pre-commit-config.yaml:
YAML
# 参考配置
repos:
# Black - 代码格式化
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
language_version: python3.11
# isort - import排序
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
# flake8 - 代码风格检查
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
additional_dependencies: [flake8-docstrings]
# mypy - 类型检查
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [types-all]
# 其他有用的钩子
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace # 去除行尾空格
- id: end-of-file-fixer # 确保文件以换行符结束
- id: check-yaml # 检查YAML语法
- id: check-added-large-files # 检查大文件
args: ['--maxkb=1000']
5.2 使用pre-commit¶
Bash
# 手动运行所有钩子
pre-commit run --all-files
# 运行特定钩子
pre-commit run black
# 跳过钩子提交(不推荐)
git commit -m "message" --no-verify
# 更新钩子版本
pre-commit autoupdate
6. 项目配置示例¶
6.1 完整的pyproject.toml¶
TOML
[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "myproject"
version = "0.1.0"
description = "My awesome project"
readme = "README.md"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
]
dependencies = [
"numpy>=1.24",
"pandas>=2.0",
]
[project.optional-dependencies]
dev = [
"black>=23.0",
"isort>=5.12",
"flake8>=6.0",
"mypy>=1.0",
"pre-commit>=3.0",
"pytest>=7.0",
]
[tool.black]
line-length = 88
target-version = ['py311']
[tool.isort]
profile = "black"
line_length = 88
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
6.2 VS Code配置¶
.vscode/settings.json:
JSON
{
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "88"],
"python.sortImports.args": ["--profile", "black"],
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.mypyEnabled": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
}
7. 代码审查清单¶
提交代码前检查¶
- 代码是否符合PEP 8规范
- 是否有适当的文档字符串
- 变量和函数命名是否清晰
- 是否有未使用的导入
- 是否有未使用的变量
- 复杂逻辑是否有注释说明
- 是否处理了异常情况
- 测试是否通过
代码审查关注点¶
Python
# ✅ 好的代码示例
class DataProcessor:
"""处理数据的类。"""
def __init__(self, config: dict) -> None:
"""
初始化处理器。
Args:
config: 配置字典
"""
self.config = config
self.logger = logging.getLogger(__name__)
def process(self, data: pd.DataFrame) -> pd.DataFrame:
"""
处理数据。
Args:
data: 输入数据
Returns:
处理后的数据
Raises:
ValueError: 如果数据为空
"""
if data.empty:
raise ValueError("数据不能为空")
try:
result = self._transform(data)
self.logger.info(f"处理完成: {len(result)} 条记录")
return result
except Exception as e:
self.logger.error(f"处理失败: {e}")
raise
📝 练习¶
练习1: 格式化现有代码¶
练习2: 配置pre-commit¶
Bash
# 1. 在你的项目中安装pre-commit
# 2. 创建.pre-commit-config.yaml文件
# 3. 配置black、isort、flake8
# 4. 运行pre-commit install
# 5. 尝试提交代码,观察自动格式化效果
练习3: 代码审查¶
Python
# 找出以下代码中的所有规范问题
import os,sys
import numpy as np
def processData(data):
x=data+1
return x
class my_class:
def __init__(self):
self.x=1
def do_something(self):
print("doing something")
🎯 自我检查¶
- 理解PEP 8的核心规范
- 掌握命名规范(变量、函数、类、常量)
- 会使用Black格式化代码
- 会使用isort整理导入
- 会使用flake8检查代码风格
- 会配置pre-commit钩子
- 会编写规范的文档字符串
- 理解代码审查的重要性
📚 延伸阅读¶
下一步: 05 - 版本控制