应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行。
推荐:
# 与左括号对齐
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)
不推荐:
# 没有使用垂直对齐时,禁止把参数放在第一行
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个空格
foo = long_function_name(
var_one, var_two,
var_three, var_four)
当if语句的条件部分长到需要换行写的时候,注意可以在两个字符关键字的连接处(比如if),增加一个空格,再增加一个左括号来创造一个4
空格缩进的多行条件。这会与if语句内同样使用4空格缩进的代码产生视觉冲突。PEP没有明确指明要如何区分i发的条件代码和内嵌代码。可使
用的选项包括但不限于下面几种情况:
# 没有额外的缩进
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()
(可以参考下面关于是否在二进制运算符之前或之后截断的讨论)
在多行结构中的大括号/中括号/小括号的右括号可以与内容对齐单独起一行作为最后一行的第一个字符,就像这样:
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',
)
Tabs or Spaces? 制表符还是空格?
空格是首选的缩进方式。
制表符只能用于与同样使用制表符缩进的代码保持一致。
Python3不允许同时使用空格和制表符的缩进。
混合使用制表符和空格缩进的Python2代码应该统一转成空格。
当在命令行加入-t选项执行Python2时,它会发出关于非法混用制表符与空格的警告。当使用–tt时,这些警告会变成错误。强烈建议使用这样
的参数。
Maximum Line Length 行的最大长度
所有行限制的最大字符数为79。
没有结构化限制的大块文本(文档字符或者注释),每行的最大字符数限制在72。
限制编辑器窗口宽度可以使多个文件并行打开,并且在使用代码检查工具(在相邻列中显示这两个版本)时工作得很好。
大多数工具中的默认封装破坏了代码的可视化结构,使代码更难以理解。避免使用编辑器中默认配置的80窗口宽度,即使工具在帮你折行时在
最后一列放了一个标记符。某些基于Web的工具可能根本不提供动态折行。
一些团队更喜欢较长的行宽。如果代码主要由一个团队维护,那这个问题就能达成一致,可以把行长度从80增加到100个字符(更有效的做法
是将行最大长度增加到99个字符),前提是注释和文档字符串依然已72字符折行。
Python标准库比较保守,需要将行宽限制在79个字符(文档/注释限制在72)。
较长的代码行选择Python在小括号,中括号以及大括号中的隐式续行方式。通过小括号内表达式的换行方式将长串折成多行。这种方式应该优
先使用,而不是使用反斜杠续行。
反斜杠有时依然很有用。比如,比较长的,多个with状态语句,不能使用隐式续行,所以反斜杠是可以接受的:
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语句。
确保在续行进行适当的缩进。
Should a line break before or after a binary operator? 在二元运算符之前应该换行吗?
几十年来,推荐的风格是在二元运算符之后中断。但是这回影响可读性,原因有二:操作符一般分布在屏幕上不同的列中,而且每个运算符被
移到了操作数的上一行。下面例子这个情况就需要额外注意,那些变量是相加的,那些变量是相减的:
# 不推荐: 操作符离操作数太远
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
为了解决这种可读性的问题,数学家和他们的出版商遵循了相反的约定。
统规则:“尽管段落中的公式总是在二元运算符和关系之后中断,显示出来的公式总是要在二元运算符之前中断” 。[3]
Computers and Typesetting
系列中解释了传
Donald Knuth
在他的
遵循数学的传统能产出更多可读性高的代码:
# 推荐:运算符和操作数很容易进行匹配
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
在Python代码中,允许在二元运算符之前或之后中断,只要本地的约定是一致的。对于新代码,建议使用Knuth的样式。
Blank Lines 空行
顶层函数和类的定义,前后用两个空行隔开。
类里的方法定义用一个空行隔开。
相关的功能组可以用额外的空行(谨慎使用)隔开。一堆相关的单行代码之间的空白行可以省略(例如,一组虚拟实现 dummy
implementations)。
在函数中使用空行来区分逻辑段(谨慎使用)。
Python接受control-L(即^L)换页符作为空格;许多工具把这些字符当作页面分隔符,所以你可以在文件中使用它们来分隔相关段落。请注
意,一些编辑器和基于Web的代码阅读器可能无法识别control-L为换页,将在其位置显示另一个字形。
Source File Encoding 源文件编码
Python核心发布版本中的代码总是以UTF-8格式编码(或者在Python2中用ASCII编码)。
使用ASCII(在Python2中)或UTF-8(在Python3中)编码的文件不应具有编码声明。
在标准库中,非默认的编码应该只用于测试,或者当一个注释或者文档字符串需要提及一个包含内ASCII字符编码的作者名字的时候;否则,
使用\x,\u,\U , 或者 \N 进行转义来包含非ASCII字符。
对于Python 3和更高版本,标准库规定了以下策略(参见
):Python标准库中的所有标识符必须使用ASCII标识符,并在可行的情
况下使用英语单词(在许多情况下,缩写和技术术语是非英语的)。此外,字符串文字和注释也必须是ASCII。唯一的例外是(a)测试非ASCI
I特征的测试用例,以及(b)作者的名称。作者的名字如果不使用拉丁字母拼写,必须提供一个拉丁字母的音译。
PEP 3131
鼓励具有全球受众的开放源码项目采取类似的政策。
Imports 导入
导入通常在分开的行,例如:
推荐: import os
import sys
不推荐: import sys, os
但是可以这样:
from subprocess import Popen, PIPE
导入总是位于文件的顶部,在模块注释和文档字符串之后,在模块的全局变量与常量之前。
导入应该按照以下顺序分组:
1.
2.
3.
标准库导入
相关第三方库导入
本地应用/库特定导入
你应该在每一组导入之间加入空行。
推荐使用绝对路径导入,如果导入系统没有正确的配置(比如包里的一个目录在sys.path里的路径后),使用绝对路径会更加可读并
且性能更好(至少能提供更好的错误信息):
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
然而,显示的指定相对导入路径是使用绝对路径的一个可接受的替代方案,特别是在处理使用绝对路径导入不必要冗长的复杂包布局时
:
from . import sibling
from .sibling import example
标准库要避免使用复杂的包引入结构,而总是使用绝对路径。
不应该使用隐式相对路径导入,并且在Python 3中删除了它。
当从一个包含类的模块中导入类时,常常这么写:
from myclass import MyClass
from foo.bar.yourclass import YourClass
如果上述的写法导致名字的冲突,那么这么写:
import myclass
import foo.bar.yourclass
然后使用“
myclass.MyClass
”和“
foo.bar.yourclass.YourClass
”。
避免通配符的导入(from import
*),因为这样做会不知道命名空间中存在哪些名字,会使得读取接口和许多自动化工具之间产生混淆。对于通配符的导入,有一个防
御性的做法,即将内部接口重新发布为公共API的一部分(例如,用可选加速器模块的定义覆盖纯Python实现的接口,以及重写那些
事先不知道的定义)。
当以这种方式重新发布名称时,以下关于公共和内部接口的准则仍然适用。
Module level dunder names 模块级的“呆”名
像__all__ , __author__ , __version__
等这样的模块级“呆名“(也就是名字里有两个前缀下划线和两个后缀下划线),应该放在文档字符串的后面,以及除from __future__
之外的import表达式前面。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
String Quotes 字符串引号
在Python中,单引号和双引号字符串是相同的。PEP不会为这个给出建议。选择一条规则并坚持使用下去。当一个字符串中包含单引号或者双
引号字符的时候,使用和最外层不同的符号来避免使用反斜杠,从而提高可读性。
对于三引号字符串,总是使用双引号字符来与
PEP 257
中的文档字符串约定保持一致。
Whitespace in Expressions and Statements 表达式和语句中的空格
Pet Peeves 不能忍受的事情
在下列情况下,避免使用无关的空格:
紧跟在小括号,中括号或者大括号后。
Yes: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
紧贴在逗号、分号或者冒号之前。
Yes: if x == 4: print x, y; x, y = y, x
No: if x == 4 : print x , y ; x , y = y , x
然而,冒号在切片中就像二元运算符,在两边应该有相同数量的空格(把它当做优先级最低的操作符)。在扩展的切片操作中,所有
的冒号必须有相同的间距。例外情况:当一个切片参数被省略时,空格就被省略了。
推荐:
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]
不推荐:
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]
为了和另一个赋值语句对齐,在赋值运算符附件加多个空格。
推荐:
x = 1
y = 2
long_variable = 3
不推荐:
x = 1
y = 2
long_variable = 3
Other Recommendations 其他建议
避免在尾部添加空格。因为尾部的空格通常都看不见,会产生混乱:比如,一个反斜杠后面跟一个空格的换行符,不算续行标记。有
些编辑器不会保留尾空格,并且很多项目(像CPython)在pre-commit的挂钩调用中会过滤掉尾空格。
总是在二元运算符两边加一个空格:赋值(=),增量赋值(+=,-=),比较(==,<,>,!=,<>,<=,>=,in,not,in,is,is
not),布尔(and, or, not)。
如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断;但是,不要使用一
个以上的空格,并且在二元运算符的两边使用相同数量的空格。
推荐:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
不推荐:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
在制定关键字参数或者默认参数值的时候,不要在=附近加上空格。
推荐:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
不推荐:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
功能型注释应该使用冒号的一般性规则,并且在使用->的时候要在两边加空格。(参考下面的
功能注释
得到能够多信息)
推荐:
def munge(input: AnyStr): ...
def munge() -> AnyStr: ...
不推荐:
def munge(input:AnyStr): ...
def munge()->PosInt: ...
当给有类型备注的参数赋值的时候,在=两边添加空格(仅针对那种有类型备注和默认值的参数)。
推荐: