写出地道 Python 代码:从风格到实践的五个维度

2026-05-26 13 预计阅读时间:1 分钟
来源:realpython.com AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:8 分钟

"Pythonic"不是一个空洞的口号——它指的是用 Python 社区公认的最佳方式解决问题,让代码读起来像 Python 而不是移植过来的 C 或 Java。一篇 20 道题的测验把 Pythonic 的核心拆成了几个方向:Zen of Python、PEP 8、代码质量、类型检查、文档。下面沿着这些维度,把容易踩的坑和可以立刻用的写法摊开讲。

Zen of Python 不只是装饰

在终端里敲一行就能看到全部 19 条格言:

python -c "import this"

多数人记得 Simple is better than complex,但容易忽略几条实操意义更大的:

  • There should be one-- and preferably only one --obvious way to do it.——同一个需求,社区有惯用写法,别发明新花样。遍历带索引就用 enumerate,别手动维护计数器。
  • Readability counts.——可读性不是"能跑就行",而是六个月后你自己还能一眼看懂。

这两条直接决定了你该不该用某个"聪明"的写法。

PEP 8:格式是团队协作的地基

PEP 8 的规则很细,但日常真正高频影响可读性的就几条:

规则 常见违规 正确写法
缩进 4 空格 混用 Tab 全文件 4 空格
行宽 79 字符 一行塞 120+ 字符 适当换行、提取变量
比较 Noneis if x == None if x is None
避免多余空格 spam( 1 ) spam(1)

用工具比用人眼靠谱。装好 flake8,提交前跑一遍:

pip install flake8
flake8 your_project/ --max-line-length=79 --statistics

输出会告诉你哪行超宽、哪行有多余空格、哪个变量没用到。把这条加进 CI,格式问题就不靠自觉了。

代码质量:用惯用写法替代"翻译式"代码

从其他语言转过来的人最容易写出"能跑但不 Pythonic"的代码。几个典型对照:

列表构造——别用循环 append,用推导式:

# 不 Pythonic:手动循环拼接
squares = []
for x in range(10):
    squares.append(x ** 2)

# Pythonic:一行推导式,意图清晰
squares = [x ** 2 for x in range(10)]

条件判断——别写空 if 分支:

# 不 Pythonic:先写空分支再写 else
if not user.is_active:
    pass  # 什么也不做
else:
    send_notification(user)

# Pythonic:直接判断正向条件
if user.is_active:
    send_notification(user)

字典取值——别手动检查 key:

# 不 Pythonic:先检查再取值
if 'email' in contact:
    email = contact['email']
else:
    email = 'default@example.com'

# Pythonic:get 一行搞定
email = contact.get('email', 'default@example.com')

遍历带索引——别维护计数器:

# 不 Pythonic
i = 0
for item in items:
    print(i, item)
    i += 1

# Pythonic
for i, item in enumerate(items):
    print(i, item)

这些不是"语法糖偏好",而是社区共识——推导式比循环 append 少一层嵌套,get 比手动检查少一次查找,读的人脑负担更小。

类型检查:让 IDE 和工具替你守门

Python 3.5+ 引入了类型注解(PEP 484),3.9+ 之后内置类型可以直接写 list[str] 而不用从 typing 导入。类型注解不改变运行行为,但给 mypy 和 IDE 提供了检查依据:

from __future__ import annotations

def merge_configs(
    base: dict[str, int],
    overrides: dict[str, int],
) -> dict[str, int]:
    """合并两层配置,overrides 中相同的 key 覆盖 base。"""
    return {**base, **overrides}

# mypy 会捕获这类错误
result = merge_configs({"a": 1}, {"b": "oops"})  # mypy 报错:str 不是 int

跑检查:

pip install mypy
mypy your_project/ --strict

--strict 模式下,所有函数必须有注解、所有变量必须能推断类型。起步阶段可以先用 --ignore-missing-imports 降低门槛,逐步收紧。

类型注解的另一个好处:IDE 悬停提示和自动补全变得精确,重构时改一个字段类型,所有引用处立刻标红。

文档:写对人有用的 docstring

测验里专门考了文档规范。Python 社区的主流格式是 Google 风格或 Sphinx/reST 风格,选一种在整个项目里统一就行。Google 风格更易读:

def fetch_user(user_id: int, timeout: float = 5.0) -> dict[str, str]:
    """从远程服务拉取用户信息。

    Args:
        user_id: 用户唯一标识,正整数。
        timeout: 请求超时秒数,默认 5.0。

    Returns:
        包含 name 和 email 的字典。

    Raises:
        ValueError: user_id <= 0 时抛出。
        ConnectionError: 网络不可达或超时时抛出。
    """
    if user_id <= 0:
        raise ValueError("user_id must be positive")
    # ... 实际请求逻辑
    return {"name": "Alice", "email": "alice@example.com"}

模块顶部也要有 docstring——一句话说清楚这个文件干什么,再补一段详细说明。这样 help(your_module) 就有完整输出,新人不用翻 README。

实操清单:把 Pythonic 落到日常

把上面几条收成一个可以逐项勾选的清单,每次提交前过一遍:

  1. 格式flake8 无报错,行宽 ≤ 79,缩进 4 空格,None 比较用 is
  2. 惯用写法:列表/字典构造用推导式或 get,遍历用 enumerate / zip,展开用 *,别手动循环拼接。
  3. 类型注解:公开函数全部加注解,mypy --strict 通过(或至少 mypy 无错误)。
  4. 文档:每个公开函数有 Google 风格 docstring,模块顶部有概述。
  5. 简洁性:删掉空 if 分支、多余中间变量、只用到一次的临时列表。

一个最小可跑的验证脚本,把五项检查串起来:

#!/usr/bin/env bash
set -e

echo "=== flake8 ==="
flake8 src/ --max-line-length=79

echo "=== mypy ==="
mypy src/ --ignore-missing-imports

echo "=== docstring coverage ==="
python -c "
import ast, sys, pathlib
missing = []
for f in pathlib.Path('src').rglob('*.py'):
    tree = ast.parse(f.read_text())
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            if not ast.get_docstring(node):
                missing.append(f'{f.name}:{node.lineno} {node.name}')
if missing:
    for m in missing:
        print(f'MISSING docstring: {m}')
    sys.exit(1)
else:
    print('All public functions have docstrings.')
"

echo "All checks passed."

把这段存成 check_pythonic.sh,加进 CI 或本地 pre-commit hook,Pythonic 就不再是"知道但没做"的事了。


Pythonic 的本质不是追求"短"或"炫",而是让代码的意图和 Python 的惯用表达对齐——读的人不需要猜,工具不需要放过隐患。从格式、惯用写法、类型、文档四个方向同时收紧,代码质量会在几周内肉眼可见地往上走。


相关推荐