Python 教程 09:Python 编码规范(PEP 8)

“代码的阅读次数远远多于编写次数。”

PEP 8 是 Python 官方的编码规范,定义了如何写出"Pythonic"的代码。遵循这些规范,你的代码会更专业、更易读、更容易被其他 Python 程序员理解。

1. 什么是 PEP 8

PEP (Python Enhancement Proposal) 是 Python 增强提案。PEP 8 专门定义了 Python 代码的风格指南。

核心思想

  • 代码更多是被阅读,而不是被编写
  • 一致性很重要
  • 可读性至上

完整文档:https://peps.python.org/pep-0008/

2. 缩进和空格

使用 4 个空格缩进

# 正确
def hello():
    print("Hello")
    if True:
        print("World")

# 错误:使用Tab或2个空格
def hello():
  print("Hello")  # 2个空格,不推荐

续行对齐

# 方法1:对齐左括号
result = some_function(argument1, argument2,
                      argument3, argument4)

# 方法2:悬挂缩进
result = some_function(
    argument1, argument2,
    argument3, argument4
)

# 列表、字典的续行
my_list = [
    1, 2, 3,
    4, 5, 6,
]  # 末尾逗号是好习惯

3. 空行

类和函数之间

# 顶层函数和类之间空2行
def function1():
    pass


def function2():
    pass


class MyClass:
    pass


class AnotherClass:
    pass

方法之间

class MyClass:
    # 类中的方法之间空1行
    def method1(self):
        pass

    def method2(self):
        pass

函数内部逻辑分组

def complex_function():
    # 初始化部分
    x = 10
    y = 20

    # 计算部分
    result = x + y

    # 返回结果
    return result

4. 最大行长度

每行不超过 79 个字符(文档字符串/注释不超过 72 个字符)。

# 过长的行需要换行
with open('/path/to/some/file/you/want/to/read') as file_1, \
     open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

# 使用括号自然换行(推荐)
result = (some_variable + another_variable
          - yet_another_variable)

为什么 79 个字符

  • 传统终端宽度是 80 字符
  • 方便并排查看两个文件
  • 强制你写简洁的代码

5. 导入

导入顺序

# 1. 标准库
import os
import sys

# 2. 第三方库
import requests
import numpy as np

# 3. 本地模块
from myproject import mymodule

导入规范

# 正确:每次导入一个模块
import os
import sys

# 不推荐:一行导入多个
import os, sys

# 正确:from导入可以一行多个
from subprocess import Popen, PIPE

# 避免通配符导入
# from module import *  # 不推荐

6. 命名约定

变量和函数

# 小写,单词用下划线分隔(snake_case)
user_name = "Alice"
total_count = 100

def calculate_sum(numbers):
    return sum(numbers)

常量

# 全大写,单词用下划线分隔
MAX_SIZE = 100
DEFAULT_TIMEOUT = 30
PI = 3.14159

类名

# 首字母大写的驼峰命名(PascalCase)
class UserManager:
    pass

class HTTPConnection:
    pass

私有变量和方法

class MyClass:
    def __init__(self):
        self.public_var = "公开"
        self._protected_var = "受保护"
        self.__private_var = "私有"

    def public_method(self):
        pass

    def _protected_method(self):
        pass

    def __private_method(self):
        pass
  • 单下划线_:受保护(约定)
  • 双下划线__:私有(名称改编)

7. 表达式和语句

比较

# 正确
if x is None:
    pass

if x is not None:
    pass

# 不要用==比较None
# if x == None:  # 不推荐

# 布尔值比较
if is_valid:  # 正确
    pass

# if is_valid == True:  # 不推荐

字符串

# 使用is检查空字符串
if not my_string:  # 推荐
    pass

# if my_string == "":  # 不推荐

# 字符串拼接
# 少量拼接用+
name = "Hello" + " " + "World"

# 大量拼接用join
words = ["Hello", "World", "Python"]
sentence = " ".join(words)

lambda 函数

# 简单的用lambda
square = lambda x: x ** 2

# 复杂的用def
def complex_function(x):
    result = x ** 2
    result += 10
    return result

8. 注释

行注释

# 注释应该完整的句子,首字母大写
x = 5  # 这是一个解释性注释

# 注释要和代码保持同步
# 过时的注释比没有注释更糟糕

文档字符串

def calculate_area(radius):
    """
    计算圆的面积。

    Args:
        radius (float): 圆的半径

    Returns:
        float: 圆的面积

    Examples:
        >>> calculate_area(5)
        78.53975
    """
    return 3.14159 * radius ** 2


class Calculator:
    """
    简单的计算器类。

    提供基本的数学运算功能。
    """

    def add(self, a, b):
        """返回两数之和。"""
        return a + b

9. 编程建议

使用 is 比较单例

# 正确
if x is None:
    pass

if x is not None:
    pass

# 错误
# if x == None:

异常处理要具体

# 好
try:
    value = int(user_input)
except ValueError:
    print("无效的数字")

# 不好:捕获所有异常
# try:
#     value = int(user_input)
# except:  # 太宽泛
#     pass

使用 with 处理资源

# 好
with open('file.txt') as f:
    data = f.read()

# 不好
# f = open('file.txt')
# data = f.read()
# f.close()  # 可能忘记关闭

字符串前缀

# 保持一致的引号风格
name = "Alice"  # 或 'Alice'

# 原始字符串
path = r"C:\Users\name"

# f-string
message = f"Hello, {name}"

10. 工具推荐

检查工具

# pylint:全面的代码检查
pylint myfile.py

# flake8:轻量级检查
flake8 myfile.py

# pycodestyle:专门检查PEP 8
pycodestyle myfile.py

格式化工具

# black:自动格式化(最推荐)
black myfile.py

# autopep8:自动修复PEP 8问题
autopep8 --in-place myfile.py

编辑器配置

在 VS Code 中安装 Python 扩展,会自动提示 PEP 8 违规。

11. 何时打破规则

PEP 8 也说了:愚蠢的一致性是头脑简单的妖怪。

可以打破规则的情况:

  1. 遵循规则会降低可读性
  2. 与周围代码保持一致(即使它违反 PEP 8)
  3. 代码是在 PEP 8 之前写的
  4. 兼容性需要

12. 小结

PEP 8 的核心要点:

  • 缩进:4 个空格
  • 空行:函数间 2 行,方法间 1 行
  • 行长:不超过 79 字符
  • 导入:标准库、第三方、本地
  • 命名:snake_case(变量/函数)、PascalCase(类)、UPPER_CASE(常量)
  • 注释:清晰、同步、文档字符串
  • 工具:使用 black、pylint 自动化

遵循 PEP 8 不仅是写出好代码,更是展示专业素养,方便团队协作。


练习题

  1. 安装并运行flake8检查你之前写的代码
  2. 重构一段不符合 PEP 8 的代码,使其符合规范
  3. 为你写过的函数添加完整的文档字符串

思考题

为什么 Python 社区如此重视代码风格的一致性?这对开源项目有什么好处?


本文代码示例


相关阅读