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 个空格缩进

1# 正确
2def hello():
3    print("Hello")
4    if True:
5        print("World")
6
7# 错误:使用Tab或2个空格
8def hello():
9  print("Hello")  # 2个空格,不推荐

续行对齐

 1# 方法1:对齐左括号
 2result = some_function(argument1, argument2,
 3                      argument3, argument4)
 4
 5# 方法2:悬挂缩进
 6result = some_function(
 7    argument1, argument2,
 8    argument3, argument4
 9)
10
11# 列表、字典的续行
12my_list = [
13    1, 2, 3,
14    4, 5, 6,
15]  # 末尾逗号是好习惯

3. 空行

类和函数之间

 1# 顶层函数和类之间空2行
 2def function1():
 3    pass
 4
 5
 6def function2():
 7    pass
 8
 9
10class MyClass:
11    pass
12
13
14class AnotherClass:
15    pass

方法之间

1class MyClass:
2    # 类中的方法之间空1行
3    def method1(self):
4        pass
5
6    def method2(self):
7        pass

函数内部逻辑分组

 1def complex_function():
 2    # 初始化部分
 3    x = 10
 4    y = 20
 5
 6    # 计算部分
 7    result = x + y
 8
 9    # 返回结果
10    return result

4. 最大行长度

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

1# 过长的行需要换行
2with open('/path/to/some/file/you/want/to/read') as file_1, \
3     open('/path/to/some/file/being/written', 'w') as file_2:
4    file_2.write(file_1.read())
5
6# 使用括号自然换行(推荐)
7result = (some_variable + another_variable
8          - yet_another_variable)

为什么 79 个字符

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

5. 导入

导入顺序

 1# 1. 标准库
 2import os
 3import sys
 4
 5# 2. 第三方库
 6import requests
 7import numpy as np
 8
 9# 3. 本地模块
10from myproject import mymodule

导入规范

 1# 正确:每次导入一个模块
 2import os
 3import sys
 4
 5# 不推荐:一行导入多个
 6import os, sys
 7
 8# 正确:from导入可以一行多个
 9from subprocess import Popen, PIPE
10
11# 避免通配符导入
12# from module import *  # 不推荐

6. 命名约定

变量和函数

1# 小写,单词用下划线分隔(snake_case)
2user_name = "Alice"
3total_count = 100
4
5def calculate_sum(numbers):
6    return sum(numbers)

常量

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

类名

1# 首字母大写的驼峰命名(PascalCase)
2class UserManager:
3    pass
4
5class HTTPConnection:
6    pass

私有变量和方法

 1class MyClass:
 2    def __init__(self):
 3        self.public_var = "公开"
 4        self._protected_var = "受保护"
 5        self.__private_var = "私有"
 6
 7    def public_method(self):
 8        pass
 9
10    def _protected_method(self):
11        pass
12
13    def __private_method(self):
14        pass
  • 单下划线_:受保护(约定)
  • 双下划线__:私有(名称改编)

7. 表达式和语句

比较

 1# 正确
 2if x is None:
 3    pass
 4
 5if x is not None:
 6    pass
 7
 8# 不要用==比较None
 9# if x == None:  # 不推荐
10
11# 布尔值比较
12if is_valid:  # 正确
13    pass
14
15# if is_valid == True:  # 不推荐

字符串

 1# 使用is检查空字符串
 2if not my_string:  # 推荐
 3    pass
 4
 5# if my_string == "":  # 不推荐
 6
 7# 字符串拼接
 8# 少量拼接用+
 9name = "Hello" + " " + "World"
10
11# 大量拼接用join
12words = ["Hello", "World", "Python"]
13sentence = " ".join(words)

lambda 函数

1# 简单的用lambda
2square = lambda x: x ** 2
3
4# 复杂的用def
5def complex_function(x):
6    result = x ** 2
7    result += 10
8    return result

8. 注释

行注释

1# 注释应该完整的句子,首字母大写
2x = 5  # 这是一个解释性注释
3
4# 注释要和代码保持同步
5# 过时的注释比没有注释更糟糕

文档字符串

 1def calculate_area(radius):
 2    """
 3    计算圆的面积。
 4
 5    Args:
 6        radius (float): 圆的半径
 7
 8    Returns:
 9        float: 圆的面积
10
11    Examples:
12        >>> calculate_area(5)
13        78.53975
14    """
15    return 3.14159 * radius ** 2
16
17
18class Calculator:
19    """
20    简单的计算器类。
21
22    提供基本的数学运算功能。
23    """
24
25    def add(self, a, b):
26        """返回两数之和。"""
27        return a + b

9. 编程建议

使用 is 比较单例

1# 正确
2if x is None:
3    pass
4
5if x is not None:
6    pass
7
8# 错误
9# if x == None:

异常处理要具体

 1# 好
 2try:
 3    value = int(user_input)
 4except ValueError:
 5    print("无效的数字")
 6
 7# 不好:捕获所有异常
 8# try:
 9#     value = int(user_input)
10# except:  # 太宽泛
11#     pass

使用 with 处理资源

1# 好
2with open('file.txt') as f:
3    data = f.read()
4
5# 不好
6# f = open('file.txt')
7# data = f.read()
8# f.close()  # 可能忘记关闭

字符串前缀

1# 保持一致的引号风格
2name = "Alice"  # 或 'Alice'
3
4# 原始字符串
5path = r"C:\Users\name"
6
7# f-string
8message = f"Hello, {name}"

10. 工具推荐

检查工具

1# pylint:全面的代码检查
2pylint myfile.py
3
4# flake8:轻量级检查
5flake8 myfile.py
6
7# pycodestyle:专门检查PEP 8
8pycodestyle myfile.py

格式化工具

1# black:自动格式化(最推荐)
2black myfile.py
3
4# autopep8:自动修复PEP 8问题
5autopep8 --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 社区如此重视代码风格的一致性?这对开源项目有什么好处?


本文代码示例


相关阅读