包含主要 Python 发行版中的标准库的 Python 代码的编码约定。
1.代码缩进
(1)每个缩进需要使用 4 个空格。一般使用一个Tab键。
Python 3 不允许混合使用制表符和空格来缩进。
python 2 使用 tabs 和空格的组合缩进方式应该转换为专门使用空格缩进。
延续行应该使用 Python 的隐式行在括号、括号和大括号内进行垂直对齐,或者使用悬挂缩进。使用悬挂缩进时,应考虑以下因素:第一行不应该有任何参数,进一步的缩进应该被用来清楚地区分自己作为一个延续行。
Yes:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
No:
# Arguments on first line forbidden when not using vertical
alignment.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Further indentation required as indentation is not distinguishable.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
(2)当条件一个 if 语句的一部分足够长要求编写跨多个行,值得注意的是,两个字符的组合关键字(即如果),加上一个空格,加上开括号创建一个自然 4 空间缩进的后续行多行条件。这可能会与嵌套在 if-语句中的缩进代码集产生视觉冲突,后者也会自然缩进到 4 个空格中。
# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
that_is_another_thing):
# Since both conditions are true, we can frobnicate.
do_something()
# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
and that_is_another_thing):
do_something()
(3)多行结构上的右括号/括号/括号可以排列在列表最后一行的第一个非空格字符下,如:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
2.最大行限制
将所有行限制为最多 79 个字符。对于具有较少结构限制的长文本块(文档字符串或注释),行长度应该限制为 72个字符。
最好的换行方式是在括号、括号和大括号中使用 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())
3.运算符在行前
几十年来,推荐的样式是在二进制运算符之后换行。但这可能在两方面破坏代码的可读性:操作符往往分散在屏幕上的不同列上,每个操作符都在其操作数的上一行。因此,眼睛必须分辨哪些操作数被加,哪些被减:
为了解决这个可读性问题,数学家和他们的出版商遵循了相反的惯例。DonaldKnuth 解释了他的计算机和排版系列中的传统规则:“虽然一个段落中的公式总是在二进制操作和关系之后换行,但是显示的公式总是在二进制操作之前进行换行”,遵循数学的传统,通常会产生更易读的代码:
# Yes: easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
# No: operators sit far away from their operands
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
在 Python 代码中,允许在二进制操作符之前或之后换行,只要约定在本地是一致的。
4.空行
用两个空行包围顶级函数和类定义。
类中定义的方法(函数)通过一个空行隔开。
可以(少量地)使用额外的空行来隔开相关函数组。在一组相关的一行程序(例如一组虚拟实现)之间可以省略空行。
在函数中尽量使用空行来指明逻辑部分。
class PERSON(object):
def __init__(self):
pass
def student(self):
pass
def teacher(self):
pass
5.源文件编码
核心 Python 发行版中的代码应该始终使用 UTF-8(或 Python 2 中的 ASCII)格式。
使用 ASCII(在 Python 2 中)或 UTF-8(在 Python 3 中)的文件不应该有编码声明。
在标准库中,非默认编码只能用于测试目的,或者当注释或文档字符串需要提到包含非 ascii 字符的作者名时。否则,使用x、u、u 或N 转义是在字符串文本中包含非 ascii 数据的首选方法。
对于 Python 3.0 及以上版本,标准库规定了以下策略(请参阅 PEP3131): Python 标准库中的所有标识符必须仅使用 ascii 标识符,并且应该在可行的情况下使用英语单词(在许多情况下,使用的是非英语的缩写词和技术术语)。此外,字符串文字和注释也必须是 ASCII 格式的。唯一的例外是:(a)测试用例测试非 ascii 特性,(b) 作者的名字。不以拉丁字母(Latin alphabet-1, ISO/IEC 8859-1 字符集)为基础的作者必须在这个字符集中提供他们名字的音译。
6.导入
导入操作通常按行分开,例:
Yes:
import os
import sys
No:
import sys, os
不过也可以这样操作:
from subprocess import Popen, PIPE
import 操作总是放在文件的顶部,在任何模块注释文档之后,在模块全局和常量之前进行。
import 操作应按以下顺序进行:
1. import 标准库
2. import 相关第三方库
3. import 本地自建库
且不同类型的库以空行分割。
建议绝对导入,因为它们通常更易于阅读,并且在导入路径错误时,表现的更友好(至少能给出更友好的错误消息):
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
但是,相对于绝对导入,显式的相对导入也是一种可接受的替代方法,特别是在处理复杂的包布局时,使用绝对导入会不不可避免的冗长,例如:
from . import sibling
from . sibling import example
一个标准的库代码应该避免复杂的包布局,并始终使用绝对导入。
在 python3 中,隐式的相对导入操作不能被使用并且已被删除。
从类包模块中 import 一个类时,通常可以这样操作:
from myclass import MyClass
from foo.bar.yourclass import YourClass
如果这个 import 方法与本地名有冲突,那么就用下面显示的 import 方法:
import myclass
import foo.bar.yourclass
并使用 "myclass.MyClass" 和 "foo.bar.yourclass.YourClass" 操作需要的类。
应该避免通配符导入操作(from <module> import *),因为它们容易混淆哪些变量名是导入的,哪些是命名空间中出现的。
7.模块级"dunders"
模块级"dunders"(即名称前后各有两个下划线),如__all__、__author__、__version__等,应在模块注释之后且任何导模块语句之前写入, 除了 from __future__ 。
Python 要求__future__ 的 import 操作必须优先于除了模块注释之外的其他任何操作。例如:
"""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
8.字符串引号
在 Python 中,单引号字符串和双引号字符串是相同的。PEP8 不会对此提出建议。选择一个规则并坚持它。然而,当字符串里包含单引号或双引号字符时,使用另一个字符来避免字符串中的反斜杠。它提高了可读性。
9.表达式和语句中的空格
在以下情况下避免使用多余的空格:
在小括号,中括号或大括号内
Yes: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
在括号内的逗号后面和逗号后面的右括号之间
Yes: foo = (0,)
No: bar = (0, )
紧跟在逗号、分号或冒号之前:
Yes: if x == 4: print x, y; x, y = y, x
No: if x == 4 : print x , y ; x , y = y , x
然而,在一个切片中,冒号就像一个二进制操作符,并且两边的数量应该相等(把它当作优先级最低的操作符对待)。在扩展切片中,两个冒号必须具有相同的间距。
例外:当切片参数被省略时,空格空间被省略。
Yes:
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]
No:
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
在启动函数调用的参数列表的左括号之前:
Yes: spam(1)
No: spam (1)
在开始索引或切片的开括号之前:
Yes: dct['key'] = lst[index]
No: dct ['key'] = lst [index]
一个赋值(或其他)操作符周围的多个空格,以便与另一个操作符对齐。
Yes:
x = 1
y = 2
long_variable = 3
No:
x = 1
y = 2
long_variable = 3
10.其他推荐规范
避免尾随空格。因为它通常是不可见的,所以它可能会令人困惑:例如,反斜杠后跟空格和换行符不算作行延续标记。有些编辑器不保存它。
这些二进制操作符两边通常都会用一个空格:赋值(=),增广赋值(+=,-=等),比较(==,<,>,!=,<>,<=,>=,in, not in, is, not),布尔值(and, or, not)。
如果使用不同优先级的操作符,请考虑在优先级最低的操作符周围添加空格。但是,永远不要使用超过一个空格,并且总是在二进制运算符的两边有相同数量的空格。
Yes:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
No:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
不要在 = 符号周围使用空格来表示关键字参数或默认参数值。
Yes:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
No:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
函数注释应该使用冒号的常规规则,如果存在的话,在->箭头周围总是有空格。
Yes:
def munge(input: AnyStr): ...
def munge() -> AnyStr: ...
No:
def munge(input:AnyStr): ...
def munge()->PosInt: ...
将参数注释与默认值组合在一起时,在=符号周围使用空格(但仅限于那些同时具有注释和默认值的参数)。
Yes:
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
No:
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...
复合语句(同一行的多个语句)通常不鼓励使用。
Yes:
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
No:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
虽然有时候在一行中加上 if /for / While,但是对于多子句的语句永远不要这样做。也要避免折叠如此长的行:
No:
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()
No:
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
list, like, this)
if foo == 'blah': one(); two(); three()