P
PEP 8 Python 代码风格指南
作者:鹿Sir开发工具v1
依据 PEP 8 与现代 Python 最佳实践规范编写、审查和重构 Python 代码,涵盖代码布局、命名约定、EAFP 哲学、类型提示、异常处理与基于 pytest 的测试驱动开发。当用户编写 .py 文件、进行 Python 代码审查、重构或关注 Python 代码质量时触发。触发词:Python 代码风格、PEP 8、代码审查、代码重构。
下载量
266
点赞
66
价格
免费
技能文档
---
name: majiayu000-python-pep8-style
title: PEP 8 Python 代码风格指南
category: 开发工具
description: 依据 PEP 8 与现代 Python 最佳实践规范编写、审查和重构 Python 代码,涵盖代码布局、命名约定、EAFP 哲学、类型提示、异常处理与基于 pytest 的测试驱动开发。当用户编写 .py 文件、进行 Python 代码审查、重构或关注 Python 代码质量时触发。触发词:Python 代码风格、PEP 8、代码审查、代码重构。
---
# PEP 8 Python 代码风格指南
本技能内置 PEP 8(Python 官方代码风格指南),并融合 Google Python 风格指南与社区通行标准中的现代 Python 最佳实践。
## 技能工作流
### 步骤1:判断使用场景
符合以下任一场景时应用本技能:
- 编写需要遵循 PEP 8 标准的新 Python 代码
- 审查 Python 代码的风格合规性
- 重构 Python 代码以提升可读性
- 学习地道的 Python 编程模式
- 搭建 Python 项目结构与工具链
### 步骤2:遵循核心设计哲学
**Python 之禅(PEP 20)**
```python
import this
# Beautiful is better than ugly.
# Explicit is better than implicit.
# Simple is better than complex.
# Complex is better than complicated.
# Flat is better than nested.
# Sparse is better than dense.
# Readability counts.
# Special cases aren't special enough to break the rules.
# Although practicality beats purity.
# Errors should never pass silently.
# Unless explicitly silenced.
# In the face of ambiguity, refuse the temptation to guess.
# There should be one-- and preferably only one --obvious way to do it.
# Now is better than never.
# Although never is often better than *right* now.
# If the implementation is hard to explain, it's a bad idea.
# If the implementation is easy to explain, it may be a good idea.
# Namespaces are one honking great idea -- let's do more of those!
```
**EAFP 优于 LBYL**:Python 偏好「请求宽恕比请求许可更容易」(EAFP),而非「三思而后行」(LBYL):
```python
# EAFP(Pythonic 风格)
try:
value = data["key"]["nested"]
except KeyError:
value = default_value
# LBYL(应避免)
if "key" in data and "nested" in data["key"]:
value = data["key"]["nested"]
else:
value = default_value
```
### 步骤3:遵守结构化限制
| 要素 | 限制 | 理由 |
|------|------|------|
| 行长度 | 79-88 字符 | PEP 8 规定 79,Black 规定 88 |
| 函数长度 | ≤25 行 | 单一职责 |
| 函数参数 | ≤5 个 | 更多时使用 dataclass/kwargs |
| 嵌套深度 | ≤4 层 | 抽取为独立函数 |
| import 分组 | 3 组 | 标准库 → 第三方 → 本地 |
### 步骤4:应用关键 PEP 8 规则
**代码布局**
```python
# 每级缩进 4 个空格(禁止用 Tab)
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# 二元运算符之前换行
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction)
# 顶层定义前后空两行
class MyClass:
pass
def my_function():
pass
```
**导入(Imports)**
```python
# 标准库导入在最前
import os
import sys
from pathlib import Path
# 第三方导入其次(空行分隔)
import requests
from pydantic import BaseModel
# 本地导入最后(空行分隔)
from myapp.models import User
from myapp.utils import helpers
# 禁止通配符导入
# from module import * # BAD
```
**命名约定**
| 类型 | 约定 | 示例 |
|------|------|------|
| 模块 | 小写下划线 | `my_module.py` |
| 包 | 小写 | `mypackage` |
| 类 | PascalCase | `MyClass` |
| 函数 | snake_case | `my_function()` |
| 变量 | snake_case | `my_variable` |
| 常量 | UPPER_SNAKE_CASE | `MAX_SIZE` |
| 私有成员 | 前置单下划线 | `_internal_var` |
| 类"私有"成员 | 前置双下划线 | `__mangled` |
**空白字符**
```python
# 正确 - 运算符两侧留空格
x = 1
y = x + 2
if x == 4:
print(x, y)
# 正确 - 括号内不留空格
spam(ham[1], {eggs: 2})
foo = (0,)
# 正确 - 切片中冒号前不留空格
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3]
# 正确 - 关键字参数的 = 两侧不留空格
def complex(real, imag=0.0):
return magic(r=real, i=imag)
# 正确 - 带类型注解时 = 两侧留空格
def munge(sep: str = None): ...
```
### 步骤5:使用现代 Python 特性
**类型提示(PEP 484、585)**
```python
from typing import Optional
from collections.abc import Sequence, Mapping
# 现代类型提示(Python 3.10+)
def process_items(
items: list[str],
config: dict[str, int] | None = None,
) -> dict[str, list[str]]:
"""Process items with optional configuration."""
...
# Protocol 用于鸭子类型
from typing import Protocol
class Serializable(Protocol):
def to_dict(self) -> dict[str, Any]: ...
```
**数据类(Dataclasses)**
```python
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class User:
username: str
email: str
created_at: datetime = field(default_factory=datetime.now)
is_active: bool = True
tags: list[str] = field(default_factory=list)
def __post_init__(self) -> None:
self.email = self.email.lower()
```
**上下文管理器**
```python
from contextlib import contextmanager
# 资源操作始终使用上下文管理器
with open("file.txt") as f:
data = f.read()
# 自定义上下文管理器
@contextmanager
def database_transaction(connection):
transaction = connection.begin()
try:
yield transaction
transaction.commit()
except Exception:
transaction.rollback()
raise
```
### 步骤6:按 TDD 流程开发(推荐)
**红阶段 - 先写失败的测试**
```python
import pytest
def test_user_creation_with_valid_email():
user = User(email="test@example.com", name="Test")
assert user.email == "test@example.com"
def test_user_creation_with_invalid_email_raises():
with pytest.raises(ValueError, match="Invalid email"):
User(email="invalid", name="Test")
```
**绿阶段 - 写最小实现让测试通过**
```python
@dataclass
class User:
email: str
name: str
def __post_init__(self) -> None:
if "@" not in self.email:
raise ValueError("Invalid email format")
```
**重构阶段 - 在测试保护下改进**
```python
import re
from dataclasses import dataclass
EMAIL_PATTERN = re.compile(r"^[\w\.-]+@[\w\.-]+\.\w+$")
@dataclass
class User:
email: str
name: str
def __post_init__(self) -> None:
self._validate_email()
self.email = self.email.lower()
def _validate_email(self) -> None:
if not EMAIL_PATTERN.match(self.email):
raise ValueError(f"Invalid email format: {self.email}")
```
### 步骤7:规范异常处理
```python
# 定义具体异常
class UserNotFoundError(Exception):
"""Raised when a user cannot be found."""
def __init__(self, user_id: int) -> None:
self.user_id = user_id
super().__init__(f"User {user_id} not found")
# 使用异常链
def get_user(user_id: int) -> User:
try:
return database.fetch_user(user_id)
except DatabaseError as e:
raise UserNotFoundError(user_id) from e
# 捕获具体异常
try:
result = process_data(data)
except ValueError as e:
logger.warning("Invalid data: %s", e)
result = default_value
except (IOError, OSError) as e:
logger.error("IO error: %s", e)
raise ProcessingError("Failed to process") from e
```
### 步骤8:交付前质量自查
**代码风格**
- [ ] 符合 PEP 8(运行 `ruff check`)
- [ ] 行长 ≤88 字符(Black 标准)
- [ ] 导入分组有序(标准库 → 第三方 → 本地)
- [ ] 无通配符导入
- [ ] 命名约定一致
**类型安全**
- [ ] 所有公开函数有类型提示
- [ ] `mypy` 检查通过
- [ ] 可空类型使用 `Optional`
- [ ] 标注了返回类型
**测试**
- [ ] 先写测试(TDD)
- [ ] `pytest` 测试通过
- [ ] 覆盖边界情况
- [ ] 测试了异常场景
**文档**
- [ ] 公开 API 有 docstring(PEP 257)
- [ ] 模块级 docstring
- [ ] 复杂逻辑有说明
**现代 Python**
- [ ] 数据容器使用 dataclass
- [ ] 资源使用上下文管理器
- [ ] 采用 EAFP 模式
- [ ] 使用 f-string 格式化
### 步骤9:运行质量工具链
```bash
# 现代 Python 工具链
uv pip install ruff mypy pytest pytest-cov bandit
# 运行质量检查
ruff check . # 代码检查(替代 flake8、isort)
ruff format . # 代码格式化(替代 black)
mypy . # 类型检查
pytest --cov=src # 测试并统计覆盖率
bandit -r src/ # 安全分析
```使用说明
# PEP 8 Python 代码风格指南 依据 PEP 8 与现代 Python 最佳实践编写、审查和重构 Python 代码,让代码风格统一、可读性更高。 ## 使用 安装本技能后,在对话中直接提出需求即可,例如: ``` 帮我审查这段 Python 代码是否符合 PEP 8 用 pytest 按 TDD 流程实现一个邮箱校验类 ``` ## 工作原理 技能内置 PEP 8 规则手册与工作流:先判断使用场景(编写/审查/重构),再依次应用结构化限制、命名约定、空白规则、类型提示与异常处理规范,最后按质量清单自查并运行 ruff、mypy、pytest 等工具链完成交付。
支持平台:Qoder · QoderWork · Claude · Codex 等 AI 编程助手