前言: 为了让不同编码习惯的开发者更好的协作配合,并且形成良好的基础编码规范与风格,我们以 PEP8 为基础,修改了陈旧的规则,丰富了示例,并整理了工作中常见的不规范操作,最终形成此 Python 编码规范与风格。
注意事项
本规范适用于所有使用 Python 语言作为开发语言的软件产品。
由于 Python2 在 2020 年停止维护,建议新增的项目使用 Python3.6+,可以使用到更多的高级特性。如果项目有兼容性需求需要支持老版本 Python 的,那么不涉及的特性可以忽略。 本规范的示例采用符合 Python3.6+ 的语法。
- 必须(Mandatory):用户必须采用;
- 推荐(Preferable):用户理应采用,但如有特殊情况,可以不采用;
- 可选(Optional):用户可参考,自行决定是否采用;
未明确指明的则默认为 必须(Mandatory)。
一、编码风格
规范地代码布局有助于帮助开发者更容易地理解业务逻辑。
1.1 缩进
1.1.1 【必须】 对于每级缩进,统一要求使用4个 空格 ,而非 tab 键。 pylint:bad-indentation
.
1.1.2 【必须】 续行,要求使用括号等定限界符,并且需要垂直对齐。
正确示范
# 与定界(括号)符对齐
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 换行并增加4个额外的空格(一级缩进)
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)
复制代码
错误示范
# 当不使用垂直对齐时,第一行不允许加参数
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)
复制代码
1.1.3 【推荐】 如果包含定界符(括号,中括号,大括号)的表达式跨越多行,那么定界符的扩回符, 可以放置与最后一行的非空字符对齐或者与构造多行的开始第一个字符对齐。
正确示范
# 与最后一行的非空字符对齐
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
# 或者与开始构造多行的第一个字符对齐
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
复制代码
1.1.4 【推荐】 对于会经常改动的函数参数、列表、字典定义,建议每行一个元素,并且每行增加一个,
。
正确示范
yes = ('y', 'Y', 'yes', 'TRUE', 'True', 'true', 'On', 'on', '1') # 基本不再改变
kwlist = [
'False',
'None',
'True',
'and',
'as',
'assert',
...
'yield', # 最后一个元素也增加一个逗号 ,方便以后diff不显示此行
]
person = {
'name': 'bob',
'age': 12, # 可能经常增加字段
}
复制代码
错误示范
# 关键字会不断增加,每个元素都换行
kwlist = ['False', 'None', 'True', 'and', 'as',
'assert', 'async', ...
]
person = {'name': 'bob', 'age': 12}
复制代码
1.1.5 【可选】 对于 if 判断,一般来说尽量不要放置过多的判断条件。换行时增加 4 个额外的空格。 pycodestyle:E129 visually indented line with same indent as next logical line
.
备注:PEP8没有明确规定,以下几种都是允许的。建议使用前面2种方法,后2种会与已有的开源工具冲突。
正确示范
# 更推荐:在续行中,增加额外的缩进级别。允许 and 操作符在前
if (this_is_one_thing
and that_is_another_thing):
do_something()
# 更推荐:在续行中,增加额外的缩进级别
if (this_is_one_thing and
that_is_another_thing):
do_something()
# 允许:与定界符(括号)对齐,不需要额外的缩进
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()
复制代码
1.2 每行最大长度
1.2.1 【必须】 每行最多不超过120
个字符。每行代码最大长度限制的根本原因是过长的行会导致阅读障碍,使得缩进失效。 pylint:line-too-long
.
除了以下两种情况例外:
- 导入模块语句。
- 注释中包含的URL。
如果需要一个长的字符串,可以用括号实现隐形连接。
正确示范
x = ('This will build a very long long '
'long long long long long long string')
复制代码
1.3 空白符
1.3.1 【必须】 在表达式的赋值符号、操作符左右至少有一个空格。
正确示范
x = y + 1
复制代码
错误示范
x=y+1
x = y+1
复制代码
1.3.2 【必须】 禁止行尾空白。 pylint:trailing-whitespace
.
行尾空白虽然不会造成功能性异常,但是这些空白字符会被源码管理系统标记出来显示为差异,对开发人员造成困恼。
正确示范
# YES: 尾部没有空白符号
+ para = {}
+ para = {} # comment
复制代码
错误示范
# No: 结尾存在多余空白符号
- para = {}•••••
- para = {} # comment••••••
复制代码
1.4 操作符
1.4.1 【推荐】 Python 没有三目操作符,对于二目操作符来说,操作符允许在换行符之后出现。
备注:pycodestyle 工具与此条目相反,PEP8 推荐操作符在这之前,更具备可读性。PEP8: Should a Line Break Before or After a Binary Operator?。 屏蔽 pycodestyle:
W503 line break before binary operator
正确示范
# YES: 易于将运算符与操作数匹配,可读性高
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
复制代码
错误示范
# No: 运算符的位置远离其操作数
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
复制代码
1.5 括号
1.5.1 【必须】 tuple 元组不允许逗号结尾,显式增加括号规避。即使一个元素也加上括号。 pylint:trailing-comma-tuple
.
行尾的逗号可能导致本来要定义一个简单变量,结果变成 tuple 变量。
正确示范
trailingcomma = (['f'],)
return (1,)
复制代码
错误示范
trailingcomma = ['f'], # tuple
return 1,
复制代码
1.6 空行
1.6.1 【必须】 模块中的一级函数和类定义之间,需要空两行
。 pycodestyle:E302 expected 2 blank lines
.
1.6.2 【必须】 类中函数定义之间,空一行
。 pycodestyle:E302 expected 1 blank line
.
1.6.3 【必须】 源文件须使用且仅使用 一个换行符
作为结尾。 pylint:missing-final-newline
, trailing-newlines
.
1.6.4 【必须】 通常每个语句应该独占一行。 pylint:multiple-statements
.
如果测试结果与测试语句在一行放得下,你也可以将它们放在同一行。 如果是if
语句, 只有在没有else
时才能这样做。 特别地,绝不要对 try
/except
这样做,因为try
和exc