python编码风格:PEP 8 -- Python 代码风格指南
地址:
https://www.python.org/dev/peps/pep-0008/
PEP 8 -- Python 代码风格指南
介绍
本文档提供了 Python 编程的代码风格指南。它描述了 Python 标准库中主流代码的约定。Python 的 C 实现中的 C 代码风格指南见相应的 PEP。
本文档和 PEP 257(文档字符串约定)改编自 Guido 的《Python Style Guide》一文,并添加了 Barry 的一些风格指南。
随着时间的推移,本文档逐渐演变,随着惯例的改变,过去的约定已被淘汰。
许多项目都有自己的编码风格指南。如果出现任何冲突,应以项目特定的指南为准。
愚蠢的一致性是小人物的心魔
Guido 的一个关键见解是,代码的阅读频率远高于编写频率。这里提供的指南旨在提高代码的可读性,使其在广泛的 Python 代码中保持一致。正如 PEP 20 所说:“可读性很重要”。
风格指南是关于一致性的。风格一致很重要,项目中的一致性更重要,模块或函数中的一致性最重要。
然而,知道何时不一致也很重要——有时风格指南并不适用。如有疑问,请运用你的判断力。看看其他例子,决定什么看起来最好。不要犹豫,尽管去问!
特别是:不要为了遵守本 PEP 而破坏向后兼容性!
以下是一些其他理由可以忽略特定指南:
应用指南会使代码的可读性降低,即使是对习惯于阅读遵循本 PEP 代码的人。
与周围代码保持一致(可能是出于历史原因)——尽管这也是清理他人混乱的机会(真正的 XP 风格)。
由于问题的代码早于指南的引入,且没有其他修改代码的原因。
当代码需要与不支持风格指南推荐功能的旧版 Python 保持兼容时。
代码布局
缩进
每个缩进级别使用 4 个空格。
连续行应使用 Python 的隐式行连接(在括号、方括号和花括号内)或悬挂缩进对齐包装元素。使用悬挂缩进时应注意:第一行不应有参数,并应使用进一步的缩进来区分其为连续行。
正确:
python
复制
与左分隔符对齐
foo = long_function_name(var_one, var_two,
var_three, var_four)
使用更多的缩进来区分
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
悬挂缩进应增加一个级别
foo = long_function_name(
var_one, var_two,
var_three, var_four)
错误:
python
复制
第一行禁止使用垂直对齐
foo = long_function_name(var_one, var_two,
var_three, var_four)
需要进一步的缩进来区分
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
4 空格规则是可选的,用于连续行。
可选:
python
复制
悬挂缩进可以缩进到 4 个空格以外的位置
foo = long_function_name(
var_one, var_two,
var_three, var_four)
当 if 语句的条件部分足够长,需要跨多行编写时,值得注意的是,两个字符的关键字(即 if)加上一个空格加上一个左括号会为后续行的缩进创建自然的 4 空格缩进。这可能会与嵌套在 if 语句中的缩进代码集产生视觉冲突,后者也会缩进到 4 个空格。本 PEP 没有明确的立场来明确如何(或是否)进一步在视觉上区分这些条件行与 if 语句中的嵌套套件。在这种情况下可接受的选择包括但不限于:
python
复制
没有额外的缩进
if (this_is_one_thing and
that_is_another_thing):
do_something()
添加注释以支持编辑器中的语法高亮
if (this_is_one_thing and
that_is_another_thing):
# Since both conditions are true, we can frobnicate.
do_something()
在条件延续行上添加额外的缩进
if (this_is_one_thing
and that_is_another_thing):
do_something()
(另请参阅下面关于是否在二元运算符之前或之后中断的讨论。)
多行结构中的右大括号/方括号/圆括号可以排列在列表最后一行的第一个非空白字符下,如下所示:
python
复制
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
或者可以排列在开始多行结构的行的第一个字符下,如下所示:
python
复制
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
制表符还是空格?
空格是首选的缩进方法。
制表符应仅用于与已使用制表符缩进的代码保持一致。
Python 3 不允许混合使用制表符和空格进行缩进。
混合使用制表符和空格的 Python 2 代码应转换为仅使用空格。
当使用 -t 选项调用 Python 2 命令行解释器时,它会发出关于非法混合制表符和空格的代码的警告。当使用 -tt 时,这些警告会变成错误。强烈建议使用这些选项!
最大行长度
将所有行限制为最多 79 个字符。
对于具有较少结构限制的长文本块(如文档字符串或注释),行长度应限制为 72 个字符。
限制所需的编辑器窗口宽度使得可以并排打开多个文件,并且在使用代码审查工具时,可以在相邻列中显示两个版本。
大多数工具中的默认包装会破坏代码的可视结构,使其更难理解。选择限制为 80 个字符的窗口宽度,即使在工具包装代码时,包装也会在 80 个字符处进行。某些基于 Web 的工具可能根本不提供动态行包装。
一些团队强烈偏好更长的行长度。对于由团队专门维护的代码,可以在此问题上达成一致,将行长度限制增加到 99 个字符,前提是注释和文档字符串仍以 72 个字符换行。
Python 标准库是保守的,要求将行限制为 79 个字符(文档字符串/注释为 72 个字符)。
实现长行换行的首选方法是使用 Python 的隐式行连接(在括号、方括号和花括号内)。长行可以通过在括号内包装表达式来跨多行。这应该优先于使用反斜杠进行行连接。
有时,反斜杠可能仍然合适。例如,长的多个 with 语句不能使用隐式连接,因此反斜杠是可以接受的:
python
复制
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())
(参见前面关于多行 if 语句的讨论,以了解关于此类多行 with 语句缩进的进一步想法。)
另一个类似的情况是 assert 语句。
确保适当缩进续行。在二元运算符周围中断的首选位置是在运算符之后,而不是之前。一些例子:
python
复制
class Rectangle(Blob):
def __init__(self, width, height, color='black', emphasis=None, highlight=0): if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong' or highlight > 100): raise ValueError("sorry, you lose") if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so -- values are %s, %s" % (width, height)) Blob.__init__(self, width, height, color, emphasis, highlight)
空行
顶级函数和类定义周围用两个空行包围。
类内的方法定义用一个空行包围。
可以使用额外的空行(谨慎地)来分隔相关函数组。在一组相关单行(例如一组虚拟实现)之间可以省略空行。
在函数中谨慎使用空行来指示逻辑部分。
Python 接受 control-L(即 ^L)换页符作为空格;许多工具将这些字符视为页面分隔符,因此你可以使用它们来分隔文件相关部分的页面。请注意,某些编辑器和基于 Web 的代码查看器可能无法识别 control-L 为换页符,并会在其位置显示另一个字形。
源文件编码
Python 核心发行版中的代码应始终使用 UTF-8(或 Python 2 中的 ASCII)。
使用 ASCII(Python 2)或 UTF-8(Python 3)的文件不应有编码声明。
在标准库中,非默认编码应仅用于测试目的,或当注释或文档字符串需要提及包含非 ASCII 字符的作者姓名时;否则,使用 \x、\u、\U 或 \N 转义是在字符串文字中包含非 ASCII 数据的首选方式。
对于 Python 3.0 及更高版本,标准库规定了以下策略(参见 PEP 3131):Python 标准库中的所有标识符必须使用纯 ASCII 标识符,并且应尽可能使用英文单词(在许多情况下,缩写和技术术语使用非英文)。此外,字符串文字和注释也必须使用 ASCII。唯一的例外是 (a) 测试非 ASCII 功能的测试用例,以及 (b) 作者的姓名。名称基于拉丁字母(带有变音符号)的作者必须提供其名称的拉丁字母音译。
鼓励具有全球受众的开源项目采用类似的政策。
导入
导入通常应放在单独的行上:
正确:
python
复制
import os
import sys
错误:
python
复制
import os, sys
然而,这样是可以的:
python
复制
from subprocess import Popen, PIPE
导入应始终放在文件的顶部,紧接在任何模块注释和文档字符串之后,模块全局变量和常量之前。
导入应按以下顺序分组:
标准库导入。
相关第三方导入。
本地应用程序/库特定导入。
每组导入之间应放一个空行。
建议使用绝对导入,因为它们通常更具可读性,并且在配置错误(例如包内的目录以 sys.path 结尾)或导入覆盖标准库模块的包时表现更好:
python
复制
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
然而,显式相对导入是绝对导入的可接受替代方案,特别是在处理复杂的包布局时,使用绝对导入会不必要地冗长:
python
复制
from . import sibling
from .sibling import example
标准库代码应避免复杂的包布局,并始终使用绝对导入。
不应使用隐式相对导入,并且在 Python 3 中已移除。
当从一个包含类的模块导入类时,通常可以这样写:
python
复制
from myclass import MyClass
from foo.bar.yourclass import YourClass
如果这种拼写导致本地名称冲突,则这样写:
python
复制
import myclass
import foo.bar.yourclass
然后使用 myclass.MyClass 和 foo.bar.yourclass.YourClass。
应避免使用通配符导入(from
以这种方式重新发布名称时,以下关于公共和内部接口的指南仍然适用。
模块级双下名称
模块级“双下”名称(如 all、author、version 等)应放在模块文档字符串之后,但在任何 import 语句之前,除了 from future 导入。Python 强制要求 from future 导入必须出现在模块中的任何代码之前,除了文档字符串。
例如:
python
复制
"""This is the example module.
This module does stuff.
"""
from future import barry_as_FLUFL
all = ['a', 'b', 'c']
version = '0.1'
author = 'Cardinal Biggles'
import os
import sys
字符串引号
在 Python 中,单引号和双引号字符串是相同的。本 PEP 不会对此提出建议。选择一条规则并坚持使用即可。然而,当字符串包含单引号或双引号字符时,请使用另一种引号以避免在字符串中使用反斜杠。这提高了可读性。
对于三引号字符串,始终使用双引号字符以与 PEP 257 中的文档字符串约定保持一致。
表达式和语句中的空格
避免使用空格的情况
在以下情况下避免使用多余的空格:
紧接在括号、方括号或花括号内:
正确:
python
复制
spam(ham[1], {eggs: 2})
错误:
python
复制
spam( ham[ 1 ], { eggs: 2 } )
在尾随逗号和后面的右括号之间:
正确:
python
复制
foo = (0,)
错误:
python
复制
foo = (0, )
在逗号、分号或冒号之前:
正确:
python
复制
if x == 4: print(x, y); x, y = y, x
错误:
python
复制
if x == 4 : print(x , y) ; x , y = y , x
然而,在切片中,冒号的作用类似于二元运算符,两侧应有相等数量的空格(将其视为优先级最低的运算符)。在扩展切片中,两个冒号必须应用相同的间距。例外情况是省略了切片参数时,应省略空格:
正确:
python
复制
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
错误:
python
复制
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
在函数调用的左括号之前:
正确:
python
复制
spam(1)
错误:
python
复制
spam (1)
在索引或切片的左括号之前:
正确:
python
复制
dct['key'] = lst[index]
错误:
python
复制
dct ['key'] = lst [index]
赋值(或其他)运算符周围有多个空格以对齐其他内容:
正确:
python
复制
x = 1
y = 2
long_variable = 3
错误:
python
复制
x = 1
y = 2
long_variable = 3
其他建议
避免在任何地方使用尾随空格。因为它通常是不可见的,可能会造成混淆:例如,反斜杠后跟空格和换行符不算作行继续标记。一些编辑器不会保留它,并且许多项目(如 CPython 本身)都有预提交钩子来拒绝它。
始终在这些二元运算符周围使用单个空格:赋值(=)、增强赋值(+=、-= 等)、比较(==、<、>、!=、<>、<=、>=、in、not in、is、is not)、布尔(and、or、not)。
如果使用具有不同优先级的运算符,请考虑在最低优先级运算符周围添加空格。请自行判断;然而,永远不要使用多个空格,并且始终在二元运算符的两侧使用相同数量的空格:
正确:
python
复制
i = i + 1
submitted += 1
x = x2 - 1
hypot2 = xx + y*y
c = (a+b) * (a-b)
错误:
python
复制
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
函数注释应使用冒号的常规规则,并且在 -> 箭头周围始终有空格(如果存在)。有关更多信息,请参见 函数注释:
正确:
python
复制
def munge(input: AnyStr): ...
def munge() -> PosInt: ...
错误:
python
复制
def munge(input:AnyStr): ...
def munge()->PosInt: ...
不要使用空格来垂直对齐多行构造的标记,因为它会成为维护的负担(适用于 :、#、= 等):
正确:
python
复制
foo = 1000 # comment
long_name = 2 # comment that should not be aligned
dictionary = {
'foo': 1,
'long_name': 2,
}
错误:
python
复制
foo = 1000 # comment
long_name = 2 # comment that should not be aligned
dictionary = {
'foo' : 1,
posted on 2025-02-01 13:12 Angry_Panda 阅读(20) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
2024-02-01 深度学习的高速推理方案:如何实现工业级的神经网络推理加速
2024-02-01 中国特供阉割版4090D建议安装最新驱动,据说不然的话会报error:4090和4090D对比
2024-02-01 华为显卡已经支持pytorch计算框架
2024-02-01 nvtop —— GPU使用情况的可视化工具
2024-02-01 很好用的python游戏环境(续2):强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境
2024-02-01 很好用的python游戏环境(续):强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境
2024-02-01 python语言下的迷宫游戏的实现猜想