Introduction 介绍
This document gives coding conventions for the Python code comprising the standard library in the main Python distribution. Please see the companion informational PEP describing style guidelines for the C code in the C implementation of Python.
本文档提供了包含主 Python 发行版中标准库的 Python 代码的编码约定。请参阅配套的信息性 PEP,其中描述了 Python 的 C 实现中 C 代码的样式指南。
This document and PEP 257 (Docstring Conventions) were adapted from Guido’s original Python Style Guide essay, with some additions from Barry’s style guide [2].
本文档和 PEP 257(Docstring Conventions)改编自 Guido 的原始 Python 风格指南文章,并从 Barry 的风格指南 [2] 中添加了一些内容。
This style guide evolves over time as additional conventions are identified and past conventions are rendered obsolete by changes in the language itself.
随着其他约定的确定,以及过去的约定因语言本身的变化而过时,此风格指南会随着时间的推移而发展。
Many projects have their own coding style guidelines. In the event of any conflicts, such project-specific guides take precedence for that project.
许多项目都有自己的编码风格指南。如果发生任何冲突,则此类特定于项目的指南优先于该项目。
A Foolish Consistency is the Hobgoblin of Little Minds愚蠢的一致性是小头脑的妖精
One of Guido’s key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As PEP 20 says, “Readability counts”.
Guido 的一个关键见解是,代码的阅读频率比编写代码的频率高得多。此处提供的指南旨在提高代码的可读性,并使其在广泛的 Python 代码中保持一致。正如 PEP 20 所说,“可读性很重要”。
A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is the most important.
风格指南是关于一致性的。与此样式指南保持一致很重要。项目内的一致性更为重要。一个模块或功能内的一致性是最重要的。
However, know when to be inconsistent – sometimes style guide recommendations just aren’t applicable. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don’t hesitate to ask!
但是,要知道什么时候不一致——有时风格指南的建议并不适用。如有疑问,请使用您的最佳判断。查看其他示例并确定哪个看起来最好。不要犹豫,问!
In particular: do not break backwards compatibility just to comply with this PEP!
特别是:不要仅仅为了遵守此 PEP 而破坏向后兼容性!
Some other good reasons to ignore a particular guideline:
忽略特定准则的其他一些充分理由:
- When applying the guideline would make the code less readable, even for someone who is used to reading code that follows this PEP.
应用该指南会使代码的可读性降低,即使对于习惯于阅读遵循此 PEP 的代码的人来说也是如此。 - To be consistent with surrounding code that also breaks it (maybe for historic reasons) – although this is also an opportunity to clean up someone else’s mess (in true XP style).
与周围的代码保持一致,这些代码也会破坏它(可能是出于历史原因)——尽管这也是一个清理别人烂摊子的机会(以真正的 XP 风格)。 - Because the code in question predates the introduction of the guideline and there is no other reason to be modifying that code.
因为有问题的代码早于指南的引入,并且没有其他理由修改该代码。 - When the code needs to remain compatible with older versions of Python that don’t support the feature recommended by the style guide.
当代码需要与不支持样式指南推荐的功能的旧版本的 Python 保持兼容时。
Code Lay-out 代码布局
Indentation 凹痕
Use 4 spaces per indentation level.
每个缩进级别使用 4 个空格。
Continuation lines should align wrapped elements either vertically using Python’s implicit line joining inside parentheses, brackets and braces, or using a hanging indent [1]. When using a hanging indent the following should be considered; there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line:
连续行应使用 Python 的隐式线连接括号、括号和大括号内,或使用悬挂缩进 [1] 垂直对齐包装元素。使用悬挂压痕时,应考虑以下几点;第一行不应有参数,应使用进一步的缩进来清楚地区分自己作为延续行:
# Correct:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Add 4 spaces (an extra level of indentation) to distinguish arguments 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)
# Wrong:
# 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)
The 4-space rule is optional for continuation lines.
4 空格规则对于连续行是可选的。
Optional: 自选:
# Hanging indents *may* be indented to other than 4 spaces.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
When the conditional part of an if
-statement is long enough to require that it be written across multiple lines, it’s worth noting that the combination of a two character keyword (i.e. if
), plus a single space, plus an opening parenthesis creates a natural 4-space indent for the subsequent lines of the multiline conditional. This can produce a visual conflict with the indented suite of code nested inside the if
-statement, which would also naturally be indented to 4 spaces. This PEP takes no explicit position on how (or whether) to further visually distinguish such conditional lines from the nested suite inside the if
-statement. Acceptable options in this situation include, but are not limited to:
当 if
-语句的条件部分足够长,需要跨多行写入时,值得注意的是,两个字符的关键字(即 if
)加上一个空格加上一个左括号的组合会为多行条件语句的后续行创建一个自然的 4 个空格缩进。这可能会与嵌套在 if
-statement 中的缩进代码套件产生视觉冲突,该代码套件也会自然缩进到 4 个空格。对于如何(或是否)进一步在视觉上将此类条件行与 if
-statement 中的嵌套套件区分开来,此 PEP 没有明确的立场。在这种情况下,可接受的选项包括但不限于:
# No extra indentation.
if (this_is_one_thing and
that_is_another_thing):
do_something()
# 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()
(Also see the discussion of whether to break before or after binary operators below.)
(另请参阅下面关于在二进制运算符之前还是之后中断的讨论。
The closing brace/bracket/parenthesis on multiline constructs may either line up under the first non-whitespace character of the last line of list, as in:
多行结构上的右大括号/括号/圆括号可以排列在列表最后一行的第一个非空格字符下,如下所示:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
or it may be lined up under the first character of the line that starts the multiline construct, as in:
或者,它可以排在开始多行构造的行的第一个字符下,如下所示:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
Tabs or Spaces? 制表符还是空格?
Spaces are the preferred indentation method.
空格是首选的缩进方法。
Tabs should be used solely to remain consistent with code that is already indented with tabs.
制表符应仅用于与已使用制表符缩进的代码保持一致。
Python disallows mixing tabs and spaces for indentation.
Python 不允许混合使用制表符和空格进行缩进。
Maximum Line Length 最大线长
Limit all lines to a maximum of 79 characters.
将所有行限制为最多 79 个字符。
For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.
对于结构限制较少(文档字符串或注释)的流畅长文本块,行长度应限制为 72 个字符。
Limiting the required editor window width makes it possible to have several files open side by side, and works well when using code review tools that present the two versions in adjacent columns.
通过限制所需的编辑器窗口宽度,可以并排打开多个文件,并且在使用在相邻列中显示两个版本的代码审查工具时效果很好。
The default wrapping in most tools disrupts the visual structure of the code, making it more difficult to understand. The limits are chosen to avoid wrapping in editors with the window width set to 80, even if the tool places a marker glyph in the final column when wrapping lines. Some web based tools may not offer dynamic line wrapping at all.
大多数工具中的默认换行会破坏代码的可视结构,使其更难理解。选择这些限制是为了避免在窗口宽度设置为 80 的编辑器中换行,即使该工具在换行时将标记字形放置在最后一列中也是如此。一些基于 Web 的工具可能根本不提供动态换行。
Some teams strongly prefer a longer line length. For code maintained exclusively or primarily by a team that can reach agreement on this issue, it is okay to increase the line length limit up to 99 characters, provided that comments and docstrings are still wrapped at 72 characters.
一些团队非常喜欢更长的线路长度。对于专门或主要由可以就此问题达成一致的团队维护的代码,可以将行长度限制增加到 99 个字符,前提是注释和文档字符串仍为 72 个字符。
The Python standard library is conservative and requires limiting lines to 79 characters (and docstrings/comments to 72).
Python 标准库是保守的,要求将行限制为 79 个字符(文档字符串/注释限制为 72 个字符)。
The preferred way of wrapping long lines is by using Python’s implied line continuation inside parentheses, brackets and braces. Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation.
换行的首选方法是在括号、括号和大括号内使用 Python 的隐含行延续。通过将表达式括在括号中,可以将长行分隔在多行上。这些应优先使用,而不是使用反斜杠进行行继续。
Backslashes may still be appropriate at times. For example, long, multiple with
-statements could not use implicit continuation before Python 3.10, so backslashes were acceptable for that case:
反斜杠有时可能仍然合适。例如,在 Python 3.10 之前,long 的多个 with
-statements 不能使用隐式延续,因此在这种情况下可以接受反斜杠:
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())
(See the previous discussion on multiline if-statements for further thoughts on the indentation of such multiline with
-statements.)
(有关此类多行语句缩进的进一步想法,请参阅前面关于多行 with
if 语句的讨论。
Another such case is with assert
statements.
另一个这样的情况是 assert
声明。
Make sure to indent the continued line appropriately.
确保适当地缩进连续行。
Should a Line Break Before or After a Binary Operator?换行符应该在二进制运算符之前还是之后?
For decades the recommended style was to break after binary operators. But this can hurt readability in two ways: the operators tend to get scattered across different columns on the screen, and each operator is moved away from its operand and onto the previous line. Here, the eye has to do extra work to tell which items are added and which are subtracted:
几十年来,推荐的风格是在二进制运算符之后打破。但这会在两个方面损害可读性:运算符往往会分散在屏幕上的不同列中,并且每个运算符都从其操作数移到上一行。在这里,眼睛必须做额外的工作来分辨哪些项目被添加,哪些项目被减去:
# Wrong:
# operators sit far away from their operands
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
To solve this readability problem, mathematicians and their publishers follow the opposite convention. Donald Knuth explains the traditional rule in his Computers and Typesetting series: “Although formulas within a paragraph always break after binary operations and relations, displayed formulas always break before binary operations” [3].
为了解决这个可读性问题,数学家和他们的出版商遵循相反的惯例。唐纳德·克努斯(Donald Knuth)在他的《计算机与排版》系列中解释了传统规则:“尽管段落中的公式总是在二进制操作和关系之后中断,但显示的公式总是在二进制操作之前中断”[3]。
Following the tradition from mathematics usually results in more readable code:
遵循数学传统通常会导致代码更具可读性:
# Correct:
# easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth’s style is suggested.
在 Python 代码中,允许在二进制运算符之前或之后中断,只要约定在本地一致即可。对于新代码,建议使用 Knuth 的样式。
Blank Lines 空行
Surround top-level function and class definitions with two blank lines.
用两个空行将顶级函数和类定义括起来。
Method definitions inside a class are surrounded by a single blank line.
类中的方法定义由一个空行括起来。
Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).
可以使用额外的空行(谨慎地)分隔相关函数组。在一堆相关的单行代码(例如,一组虚拟实现)之间可以省略空行。
Use blank lines in functions, sparingly, to indicate logical sections.
在函数中谨慎使用空行来指示逻辑部分。
Python accepts the control-L (i.e. ^L) form feed character as whitespace; many tools treat these characters as page separators, so you may use them to separate pages of related sections of your file. Note, some editors and web-based code viewers may not recognize control-L as a form feed and will show another glyph in its place.
Python 接受 control-L(即 ^L)表单提要字符作为空格;许多工具将这些字符视为页面分隔符,因此您可以使用它们来分隔文件相关部分的页面。请注意,某些编辑器和基于 Web 的代码查看器可能无法将 control-L 识别为表单源,而是在其位置显示另一个字形。
Source File Encoding 源文件编码
Code in the core Python distribution should always use UTF-8, and should not have an encoding declaration.
核心 Python 发行版中的代码应始终使用 UTF-8,并且不应具有编码声明。
In the standard library, non-UTF-8 encodings should be used only for test purposes. Use non-ASCII characters sparingly, preferably only to denote places and human names. If using non-ASCII characters as data, avoid noisy Unicode characters like z̯̯͡a̧͎̺l̡͓̫g̹̲o̡̼̘ and byte order marks.
在标准库中,非 UTF-8 编码应仅用于测试目的。谨慎使用非 ASCII 字符,最好仅用于表示地点和人名。如果使用非 ASCII 字符作为数据,请避免使用嘈杂的 Unicode 字符,如 z̯̯͡a̧͎̺l̡͓̫g̹̲o̡̼̘ 和字节顺序标记。
All identifiers in the Python standard library MUST use ASCII-only identifiers, and SHOULD use English words wherever feasible (in many cases, abbreviations and technical terms are used which aren’t English).
Python 标准库中的所有标识符都必须使用仅限 ASCII 的标识符,并且应尽可能使用英语单词(在许多情况下,使用非英语的缩写和技术术语)。
Open source projects with a global audience are encouraged to adopt a similar policy.
鼓励具有全球受众的开源项目采用类似的政策。
Imports 进口
- Imports should usually be on separate lines:
进口通常应在单独的行上:# Correct: import os import sys
# Wrong: import sys, os
It’s okay to say this though:
不过可以这样说:# Correct: from subprocess import Popen, PIPE
- Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.
导入始终放在文件顶部,紧挨着任何模块注释和文档字符串之后,以及模块全局变量和常量之前。Imports should be grouped in the following order:
导入应按以下顺序分组:- Standard library imports.
标准库导入。 - Related third party imports.
相关的第三方导入。 - Local application/library specific imports.
特定于本地应用程序/库的导入。
You should put a blank line between each group of imports.
您应该在每组导入之间留一个空行。 - Standard library imports.
- Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on
sys.path
):
建议使用绝对导入,因为如果导入系统配置不正确(例如,当包内的目录最终位于 ):sys.path
import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
However, explicit relative imports are an acceptable alternative to absolute imports, especially when dealing with complex package layouts where using absolute imports would be unnecessarily verbose:
但是,显式相对导入是绝对导入的可接受替代方法,尤其是在处理复杂的包布局时,使用绝对导入会不必要地冗长:from . import sibling from .sibling import example
Standard library code should avoid complex package layouts and always use absolute imports.
标准库代码应避免复杂的包布局,并始终使用绝对导入。 - When importing a class from a class-containing module, it’s usually okay to spell this:
从包含类的模块导入类时,通常可以拼写如下:from myclass import MyClass from foo.bar.yourclass import YourClass
If this spelling causes local name clashes, then spell them explicitly:
如果此拼写导致本地名称冲突,则显式拼写它们:import myclass import foo.bar.yourclass
and use
myclass.MyClass
andfoo.bar.yourclass.YourClass
.
并使用myclass.MyClass
和foo.bar.yourclass.YourClass
. - Wildcard imports (
from <module> import *
) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools. There is one defensible use case for a wildcard import, which is to republish an internal interface as part of a public API (for example, overwriting a pure Python implementation of an interface with the definitions from an optional accelerator module and exactly which definitions will be overwritten isn’t known in advance).
应避免使用通配符导入 (from <module> import *
),因为它们会使命名空间中存在哪些名称变得不清楚,从而混淆了读取器和许多自动化工具。通配符导入有一个可辩护的用例,即将内部接口重新发布为公共 API 的一部分(例如,使用可选加速器模块中的定义覆盖接口的纯 Python 实现,以及事先不知道将覆盖哪些定义)。When republishing names this way, the guidelines below regarding public and internal interfaces still apply.
以这种方式重新发布名称时,以下有关公共和内部接口的准则仍然适用。
Module Level Dunder Names模块级名称
Module level “dunders” (i.e. names with two leading and two trailing underscores) such as __all__
, __author__
, __version__
, etc. should be placed after the module docstring but before any import statements except from __future__
imports. Python mandates that future-imports must appear in the module before any other code except docstrings:
模块级别的“dunders”(即带有两个前导下划线和两个尾随下划线的名称),如 __all__
、 、 __author__
__version__
等,应放在模块文档字符串之后,但在除 imports 之外 from __future__
的任何 import 语句之前。Python 要求 future-imports 必须出现在模块中,在除文档字符串之外的任何其他代码之前:
"""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 字符串引号
In Python, single-quoted strings and double-quoted strings are the same. This PEP does not make a recommendation for this. Pick a rule and stick to it. When a string contains single or double quote characters, however, use the other one to avoid backslashes in the string. It improves readability.
在 Python 中,单引号字符串和双引号字符串是相同的。本 PEP 不对此提出建议。选择一条规则并坚持下去。但是,当字符串包含单引号或双引号字符时,请使用另一个字符以避免字符串中的反斜杠。它提高了可读性。
For triple-quoted strings, always use double quote characters to be consistent with the docstring convention in PEP 257.
对于三引号字符串,请始终使用双引号字符,以与 PEP 257 中的文档字符串约定保持一致。
Whitespace in Expressions and Statements表达式和语句中的空格
Pet Peeves 宠物烦恼
Avoid extraneous whitespace in the following situations:
在以下情况下避免使用无关的空格:
- Immediately inside parentheses, brackets or braces:
紧接在括号、方括号或大括号内:# Correct: spam(ham[1], {eggs: 2})
# Wrong: spam( ham[ 1 ], { eggs: 2 } )
- Between a trailing comma and a following close parenthesis:
在尾随逗号和后面的右括号之间:# Correct: foo = (0,)
# Wrong: bar = (0, )
- Immediately before a comma, semicolon, or colon:
紧挨着逗号、分号或冒号:# Correct: if x == 4: print(x, y); x, y = y, x
# Wrong: if x == 4 : print(x , y) ; x , y = y , x
- However, in a slice the colon acts like a binary operator, and should have equal amounts on either side (treating it as the operator with the lowest priority). In an extended slice, both colons must have the same amount of spacing applied. Exception: when a slice parameter is omitted, the space is omitted:
但是,在切片中,冒号的作用类似于二进制运算符,并且两边的冒号数量应该相等(将其视为优先级最低的运算符)。在扩展切片中,两个冒号必须应用相同的间距。例外:省略切片参数时,省略空格:# Correct: 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]
# Wrong: ham[lower + offset:upper + offset] ham[1: 9], ham[1 :9], ham[1:9 :3] ham[lower : : step] ham[ : upper]
- Immediately before the open parenthesis that starts the argument list of a function call:
紧接在开始函数调用的参数列表的左括号之前:# Correct: spam(1)
# Wrong: spam (1)
- Immediately before the open parenthesis that starts an indexing or slicing:
紧接在开始索引或切片的左括号之前:# Correct: dct['key'] = lst[index]
# Wrong: dct ['key'] = lst [index]
- More than one space around an assignment (or other) operator to align it with another:
赋值(或其他)运算符周围有多个空格,以将其与另一个运算符对齐:# Correct: x = 1 y = 2 long_variable = 3
# Wrong: x = 1 y = 2 long_variable = 3
Other Recommendations 其他建议
- Avoid trailing whitespace anywhere. Because it’s usually invisible, it can be confusing: e.g. a backslash followed by a space and a newline does not count as a line continuation marker. Some editors don’t preserve it and many projects (like CPython itself) have pre-commit hooks that reject it.
避免在任何地方使用尾随空格。因为它通常是不可见的,所以它可能会造成混淆:例如,反斜杠后跟一个空格,换行符不算作行继续标记。一些编辑器不会保留它,许多项目(如 CPython 本身)都有拒绝它的预提交钩子。 - Always surround these binary operators with a single space on either side: assignment (
=
), augmented assignment (+=
,-=
etc.), comparisons (==
,<
,>
,!=
,<>
,<=
,>=
,in
,not in
,is
,is not
), Booleans (and
,or
,not
).
始终用两侧的单个空格将这些二进制运算符括起来:赋值 (=
+=
)、增强赋值 ( 等-=
)、比较 ( 、==
、>
、 、 )、布尔值 ( 、!=
not
and
、<>
<=
>=
in
not in
is
is not
<
or
)。 - If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator:
如果使用具有不同优先级的运算符,请考虑在优先级最低的运算符周围添加空格。使用自己的判断;但是,切勿使用多个空格,并且始终在二进制运算符的两边具有相同数量的空格:# Correct: i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b)
# Wrong: i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b)
- Function annotations should use the normal rules for colons and always have spaces around the
->
arrow if present. (See Function Annotations below for more about function annotations.):
函数注释应使用冒号的正常规则,并且->
箭头周围始终有空格(如果存在)。(有关函数注解的更多信息,请参阅下面的函数注解。# Correct: def munge(input: AnyStr): ... def munge() -> PosInt: ...
# Wrong: def munge(input:AnyStr): ... def munge()->PosInt: ...
- Don’t use spaces around the
=
sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter:
当用于指示关键字参数或用于指示未注释函数参数的默认值时,不要在=
符号周围使用空格:# Correct: def complex(real, imag=0.0): return magic(r=real, i=imag)
# Wrong: def complex(real, imag = 0.0): return magic(r = real, i = imag)
When combining an argument annotation with a default value, however, do use spaces around the
=
sign:
但是,当将参数注释与默认值组合时,请在=
符号周围使用空格:# Correct: def munge(sep: AnyStr = None): ... def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# Wrong: def munge(input: AnyStr=None): ... def munge(input: AnyStr, limit = 1000): ...
- Compound statements (multiple statements on the same line) are generally discouraged:
通常不鼓励使用复合语句(同一行上的多个语句):# Correct: if foo == 'blah': do_blah_thing() do_one() do_two() do_three()
Rather not: 宁愿不要:
# Wrong: if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()
- While sometimes it’s okay to put an if/for/while with a small body on the same line, never do this for multi-clause statements. Also avoid folding such long lines!
虽然有时可以将带有小主体的 if/for/while 放在同一行上,但切勿对多子句语句这样做。也避免折叠这么长的线!Rather not: 宁愿不要:
# Wrong: if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay()
Definitely not: 绝对不是:
# Wrong: 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()
When to Use Trailing Commas何时使用尾随逗号
Trailing commas are usually optional, except they are mandatory when making a tuple of one element. For clarity, it is recommended to surround the latter in (technically redundant) parentheses:
尾随逗号通常是可选的,除非在创建一个元素的元组时它们是必需的。为清楚起见,建议将后者括在(技术上多余的)括号中:
# Correct:
FILES = ('setup.cfg',)
# Wrong:
FILES = 'setup.cfg',
When trailing commas are redundant, they are often helpful when a version control system is used, when a list of values, arguments or imported items is expected to be extended over time. The pattern is to put each value (etc.) on a line by itself, always adding a trailing comma, and add the close parenthesis/bracket/brace on the next line. However it does not make sense to have a trailing comma on the same line as the closing delimiter (except in the above case of singleton tuples):
当尾随逗号是多余的时,当使用版本控制系统时,当值、参数或导入项的列表预计会随着时间的推移而扩展时,它们通常很有帮助。模式是将每个值(等)单独放在一行上,始终添加一个尾随逗号,并在下一行添加右括号/括号/大括号。但是,在与结束分隔符相同的行上有一个尾随逗号是没有意义的(除了上述单例元组的情况):
# Correct:
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
# Wrong:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
Comments 评论
Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!
与代码相矛盾的注释比没有注释更糟糕。当代码更改时,始终优先考虑使评论保持最新!
Comments should be complete sentences. The first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!).
评论应该是完整的句子。第一个单词应该大写,除非它是以小写字母开头的标识符(永远不要改变标识符的大小写!
Block comments generally consist of one or more paragraphs built out of complete sentences, with each sentence ending in a period.
块注释通常由一个或多个段落组成,这些段落由完整的句子组成,每个句子都以句号结尾。
You should use one or two spaces after a sentence-ending period in multi-sentence comments, except after the final sentence.
在多句注释中,您应该在句子结束句号后使用一个或两个空格,但最后一句之后除外。
Ensure that your comments are clear and easily understandable to other speakers of the language you are writing in.
确保您的评论清晰易懂,其他使用您所用语言的人也能轻松理解。
Python coders from non-English speaking countries: please write your comments in English, unless you are 120% sure that the code will never be read by people who don’t speak your language.
来自非英语国家的 Python 编码人员:请用英语写下您的评论,除非您 120% 确定代码永远不会被不会说您的语言的人阅读。
Block Comments 阻止评论
Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. Each line of a block comment starts with a #
and a single space (unless it is indented text inside the comment).
块注释通常适用于它们后面的部分(或全部)代码,并且缩进到与该代码相同的级别。块注释的每一行都以 a #
和单个空格开头(除非它是注释中的缩进文本)。
Paragraphs inside a block comment are separated by a line containing a single #
.
块注释中的段落由包含单个 #
.
Inline Comments 内联注释
Use inline comments sparingly.
谨慎使用内联注释。
An inline comment is a comment on the same line as a statement. Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.
内联注释是与语句在同一行上的注释。内联注释应与语句之间至少间隔两个空格。它们应以 # 和单个空格开头。
Inline comments are unnecessary and in fact distracting if they state the obvious. Don’t do this:
内联注释是不必要的,如果它们陈述了显而易见的内容,实际上会分散注意力。别这样:
x = x + 1 # Increment x
But sometimes, this is useful:
但有时,这很有用:
x = x + 1 # Compensate for border
Documentation Strings 文档字符串
Conventions for writing good documentation strings (a.k.a. “docstrings”) are immortalized in PEP 257.
编写良好文档字符串(又名“文档字符串”)的约定在 PEP 257 中永垂不朽。
- Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does. This comment should appear after the
def
line.
为所有公共模块、函数、类和方法编写文档字符串。文档字符串对于非公共方法不是必需的,但您应该有一个注释来描述该方法的作用。此注释应出现在该def
行之后。 - PEP 257 describes good docstring conventions. Note that most importantly, the
"""
that ends a multiline docstring should be on a line by itself:
PEP 257 描述了良好的文档字符串约定。请注意,最重要的是,结束多行文档字符串的"""
that end should be itself on a line in a line itself:"""Return a foobang Optional plotz says to frobnicate the bizbaz first. """
- For one liner docstrings, please keep the closing
"""
on the same line:
对于一个衬里文档字符串,请将结束"""
语保留在同一行上:"""Return an ex-parrot."""
Naming Conventions 命名约定
The naming conventions of Python’s library are a bit of a mess, so we’ll never get this completely consistent – nevertheless, here are the currently recommended naming standards. New modules and packages (including third party frameworks) should be written to these standards, but where an existing library has a different style, internal consistency is preferred.
Python 库的命名约定有点混乱,所以我们永远不会完全一致——尽管如此,这里是目前推荐的命名标准。新的模块和包(包括第三方框架)应该按照这些标准编写,但如果现有库具有不同的样式,则内部一致性是首选。
Overriding Principle 压倒一切的原则
Names that are visible to the user as public parts of the API should follow conventions that reflect usage rather than implementation.
作为 API 的公共部分对用户可见的名称应遵循反映用法而不是实现的约定。
Descriptive: Naming Styles描述性:命名样式
There are a lot of different naming styles. It helps to be able to recognize what naming style is being used, independently from what they are used for.
有很多不同的命名风格。它有助于识别正在使用的命名样式,而与它们的用途无关。
The following naming styles are commonly distinguished:
通常区分以下命名样式:
b
(single lowercase letter)b
(单个小写字母)B
(single uppercase letter)B
(单个大写字母)lowercase
lower_case_with_underscores
UPPERCASE
UPPER_CASE_WITH_UNDERSCORES
CapitalizedWords
(or CapWords, or CamelCase – so named because of the bumpy look of its letters [4]). This is also sometimes known as StudlyCaps.CapitalizedWords
(或CapWords,或CamelCase——因其字母的凹凸不平的外观而得名[4])。这有时也被称为 StudlyCaps。Note: When using acronyms in CapWords, capitalize all the letters of the acronym. Thus HTTPServerError is better than HttpServerError.
注意:在 CapWords 中使用首字母缩略词时,请将首字母缩略词的所有字母大写。因此,HTTPServerError 优于 HttpServerError。mixedCase
(differs from CapitalizedWords by initial lowercase character!)mixedCase
(与 CapitalizedWords 的区别在于初始小写字符!Capitalized_Words_With_Underscores
(ugly!)Capitalized_Words_With_Underscores
(丑陋!
There’s also the style of using a short unique prefix to group related names together. This is not used much in Python, but it is mentioned for completeness. For example, the os.stat()
function returns a tuple whose items traditionally have names like st_mode
, st_size
, st_mtime
and so on. (This is done to emphasize the correspondence with the fields of the POSIX system call struct, which helps programmers familiar with that.)
还有一种风格是使用一个简短的唯一前缀将相关名称组合在一起。这在 Python 中用得不多,但为了完整性而提到它。例如,该 os.stat()
函数返回一个元组,其项传统上具有 st_mode
、 st_size
st_mtime
等名称。(这样做是为了强调与 POSIX 系统调用结构的字段的对应关系,这有助于熟悉它的程序员。
The X11 library uses a leading X for all its public functions. In Python, this style is generally deemed unnecessary because attribute and method names are prefixed with an object, and function names are prefixed with a module name.
X11 库在其所有公共函数中使用前导 X。在 Python 中,这种样式通常被认为是不必要的,因为属性和方法名称以对象为前缀,而函数名称以模块名称为前缀。
In addition, the following special forms using leading or trailing underscores are recognized (these can generally be combined with any case convention):
此外,还可以识别以下使用前导或尾随下划线的特殊形式(这些形式通常可以与任何大小写约定结合使用):
_single_leading_underscore
: weak “internal use” indicator. E.g.from M import *
does not import objects whose names start with an underscore._single_leading_underscore
:弱“内部使用”指标。例如,from M import *
不导入名称以下划线开头的对象。single_trailing_underscore_
: used by convention to avoid conflicts with Python keyword, e.g. :single_trailing_underscore_
:按照惯例使用,以避免与 Python 关键字冲突,例如:tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore
: when naming a class attribute, invokes name mangling (inside class FooBar,__boo
becomes_FooBar__boo
; see below).__double_leading_underscore
:命名类属性时,调用名称修改(在类 FooBar 中,__boo
变成_FooBar__boo
;见下文)。__double_leading_and_trailing_underscore__
: “magic” objects or attributes that live in user-controlled namespaces. E.g.__init__
,__import__
or__file__
. Never invent such names; only use them as documented.__double_leading_and_trailing_underscore__
:位于用户控制的命名空间中的“魔术”对象或属性。例如__init__
,__import__
或__file__
.永远不要发明这样的名字;仅按照文档说明使用它们。
Prescriptive: Naming Conventions规范性:命名约定
Names to Avoid 要避免的名称
Never use the characters ‘l’ (lowercase letter el), ‘O’ (uppercase letter oh), or ‘I’ (uppercase letter eye) as single character variable names.
切勿使用字符“l”(小写字母 el)、“O”(大写字母 oh)或“I”(大写字母 eye)作为单字符变量名称。
In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use ‘l’, use ‘L’ instead.
在某些字体中,这些字符与数字 1 和 0 无法区分。当想使用“l”时,请改用“L”。
ASCII Compatibility ASCII 兼容性
Identifiers used in the standard library must be ASCII compatible as described in the policy section of PEP 3131.
标准库中使用的标识符必须与 PEP 3131 的策略部分所述的 ASCII 兼容。
Package and Module Names软件包和模块名称
Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
模块应具有简短的全小写名称。如果可提高可读性,则可以在模块名称中使用下划线。Python 包也应该有简短的全小写名称,但不鼓励使用下划线。
When an extension module written in C or C++ has an accompanying Python module that provides a higher level (e.g. more object oriented) interface, the C/C++ module has a leading underscore (e.g. _socket
).
当用 C 或 C++ 编写的扩展模块具有随附的 Python 模块,该模块提供更高级别(例如更面向对象)接口时,C/C++ 模块具有前导下划线(例如)。 _socket
Class Names 类名
Class names should normally use the CapWords convention.
类名通常应使用 CapWords 约定。
The naming convention for functions may be used instead in cases where the interface is documented and used primarily as a callable.
在接口被记录并主要用作可调用对象的情况下,可以使用函数的命名约定。
Note that there is a separate convention for builtin names: most builtin names are single words (or two words run together), with the CapWords convention used only for exception names and builtin constants.
请注意,内置名称有一个单独的约定:大多数内置名称是单个单词(或两个单词一起运行),CapWords 约定仅用于异常名称和内置常量。
Type Variable Names 类型变量名称
Names of type variables introduced in PEP 484 should normally use CapWords preferring short names: T
, AnyStr
, Num
. It is recommended to add suffixes _co
or _contra
to the variables used to declare covariant or contravariant behavior correspondingly:
PEP 484 中引入的变量类型名称通常应使用 CapWords,而首选短名称: T
、 AnyStr
、 Num
.建议在用于相应声明协变或逆变行为的变量中添加后缀 _co
或 _contra
:
from typing import TypeVar
VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
Exception Names 异常名称
Because exceptions should be classes, the class naming convention applies here. However, you should use the suffix “Error” on your exception names (if the exception actually is an error).
由于异常应为类,因此此处适用类命名约定。但是,应在异常名称上使用后缀“Error”(如果异常实际上是错误)。
Global Variable Names 全局变量名称
(Let’s hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.
(我们希望这些变量只在一个模块中使用。这些约定与函数的约定大致相同。
Modules that are designed for use via from M import *
should use the __all__
mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are “module non-public”).
设计用于 via from M import *
的模块应使用该 __all__
机制来防止导出全局变量,或者使用在此类全局变量前面加上下划线的旧约定(您可能希望这样做以指示这些全局变量是“模块非公共”)。
Function and Variable Names函数和变量名称
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
函数名称应为小写,必要时用下划线分隔单词以提高可读性。
Variable names follow the same convention as function names.
变量名称遵循与函数名称相同的约定。
mixedCase is allowed only in contexts where that’s already the prevailing style (e.g. threading.py), to retain backwards compatibility.
mixedCase 只允许在已经是流行样式的上下文中(例如 threading.py),以保持向后兼容性。
Function and Method Arguments函数和方法参数
Always use self
for the first argument to instance methods.
始终用于 self
实例方法的第一个参数。
Always use cls
for the first argument to class methods.
始终用于 cls
类方法的第一个参数。
If a function argument’s name clashes with a reserved keyword, it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption. Thus class_
is better than clss
. (Perhaps better is to avoid such clashes by using a synonym.)
如果函数参数的名称与保留关键字冲突,则通常最好附加单个尾随下划线,而不是使用缩写或拼写损坏。因此 class_
比 clss
.(也许更好的方法是通过使用同义词来避免这种冲突。
Method Names and Instance Variables方法名称和实例变量
Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.
根据需要使用函数命名规则:小写,单词之间用下划线分隔,以提高可读性。
Use one leading underscore only for non-public methods and instance variables.
仅对非公共方法和实例变量使用一个前导下划线。
To avoid name clashes with subclasses, use two leading underscores to invoke Python’s name mangling rules.
为避免与子类发生名称冲突,请使用两个前导下划线来调用 Python 的名称修改规则。
Python mangles these names with the class name: if class Foo has an attribute named __a
, it cannot be accessed by Foo.__a
. (An insistent user could still gain access by calling Foo._Foo__a
.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.
Python 用类名来修改这些名称:如果类 Foo 有一个名为 __a
的属性,则不能由 Foo.__a
访问。(坚持使用的用户仍可以通过调用 Foo._Foo__a
来获取访问权限。通常,应仅使用双前导下划线以避免与设计为子类的类中的属性发生名称冲突。
Note: there is some controversy about the use of __names (see below).
注意:关于__names的使用存在一些争议(见下文)。
Constants 常数
Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW
and TOTAL
.
常量通常在模块级别上定义,并以全大写字母书写,并用下划线分隔单词。示例包括 MAX_OVERFLOW
和 TOTAL
。
Designing for Inheritance继承设计
Always decide whether a class’s methods and instance variables (collectively: “attributes”) should be public or non-public. If in doubt, choose non-public; it’s easier to make it public later than to make a public attribute non-public.
始终决定类的方法和实例变量(统称为“属性”)应该是公共的还是非公共的。如有疑问,请选择非公开;稍后将其公开比将公共属性设置为非公开更容易。
Public attributes are those that you expect unrelated clients of your class to use, with your commitment to avoid backwards incompatible changes. Non-public attributes are those that are not intended to be used by third parties; you make no guarantees that non-public attributes won’t change or even be removed.
公共属性是你希望类中不相关的客户端使用的属性,并承诺避免向后不兼容的更改。非公共属性是指那些不打算被第三方使用的属性;您不保证非公共属性不会更改甚至不会被删除。
We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work).
我们在这里不使用术语“私有”,因为在 Python 中没有任何属性是真正私有的(通常没有不必要的工作量)。
Another category of attributes are those that are part of the “subclass API” (often called “protected” in other languages). Some classes are designed to be inherited from, either to extend or modify aspects of the class’s behavior. When designing such a class, take care to make explicit decisions about which attributes are public, which are part of the subclass API, and which are truly only to be used by your base class.
另一类属性是属于“子类 API”(在其他语言中通常称为“受保护”)的属性。某些类被设计为继承类,以扩展或修改类行为的各个方面。在设计此类时,请注意明确决定哪些属性是公共的,哪些属性是子类 API 的一部分,哪些属性真正只能由基类使用。
With this in mind, here are the Pythonic guidelines:
考虑到这一点,以下是 Pythonic 指南:
- Public attributes should have no leading underscores.
公共属性不应有前导下划线。 - If your public attribute name collides with a reserved keyword, append a single trailing underscore to your attribute name. This is preferable to an abbreviation or corrupted spelling. (However, notwithstanding this rule, ‘cls’ is the preferred spelling for any variable or argument which is known to be a class, especially the first argument to a class method.)
如果您的公共属性名称与保留关键字发生冲突,请在属性名称后附加一个尾随下划线。这比缩写或拼写损坏更可取。(但是,尽管有此规则,但“cls”是已知为类的任何变量或参数的首选拼写,尤其是类方法的第一个参数。Note 1: See the argument name recommendation above for class methods.
注 1:有关类方法,请参阅上面的参数名称建议。 - For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.
对于简单的公共数据属性,最好只公开属性名称,而不使用复杂的访问器/赋值器方法。请记住,如果您发现一个简单的数据属性需要增加功能行为,Python 为将来的增强提供了一条简单的途径。在这种情况下,请使用属性将函数实现隐藏在简单数据属性访问语法后面。Note 1: Try to keep the functional behavior side-effect free, although side-effects such as caching are generally fine.
注意 1:尽量保持功能行为的副作用,尽管缓存等副作用通常很好。Note 2: Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.
注 2:避免将属性用于计算成本高昂的操作;属性表示法使调用者相信访问(相对)便宜。 - If your class is intended to be subclassed, and you have attributes that you do not want subclasses to use, consider naming them with double leading underscores and no trailing underscores. This invokes Python’s name mangling algorithm, where the name of the class is mangled into the attribute name. This helps avoid attribute name collisions should subclasses inadvertently contain attributes with the same name.
如果您的类打算被子类化,并且您具有不希望子类使用的属性,请考虑使用双前导下划线和无尾随下划线来命名它们。这将调用 Python 的名称修改算法,其中类的名称被修改为属性名称。这有助于避免在子类无意中包含具有相同名称的属性时发生属性名称冲突。Note 1: Note that only the simple class name is used in the mangled name, so if a subclass chooses both the same class name and attribute name, you can still get name collisions.
注 1:请注意,在修改后的名称中仅使用简单的类名,因此,如果子类同时选择相同的类名和属性名,您仍然可能会发生名称冲突。Note 2: Name mangling can make certain uses, such as debugging and
__getattr__()
, less convenient. However the name mangling algorithm is well documented and easy to perform manually.
注2:名称修改会使某些用途变得不那么方便,例如调试和__getattr__()
,不太方便。但是,名称修改算法有据可查,易于手动执行。Note 3: Not everyone likes name mangling. Try to balance the need to avoid accidental name clashes with potential use by advanced callers.
注3:不是每个人都喜欢名字的篡改。尝试在避免意外名称冲突的需要与高级调用方的潜在使用之间取得平衡。
Public and Internal Interfaces公共接口和内部接口
Any backwards compatibility guarantees apply only to public interfaces. Accordingly, it is important that users be able to clearly distinguish between public and internal interfaces.
任何向后兼容性保证仅适用于公共接口。因此,用户必须能够清楚地区分公共接口和内部接口。
Documented interfaces are considered public, unless the documentation explicitly declares them to be provisional or internal interfaces exempt from the usual backwards compatibility guarantees. All undocumented interfaces should be assumed to be internal.
记录的接口被视为公共接口,除非文档明确声明它们是临时接口或内部接口,不受通常的向后兼容性保证的约束。所有未记录的接口都应假定为内部接口。
To better support introspection, modules should explicitly declare the names in their public API using the __all__
attribute. Setting __all__
to an empty list indicates that the module has no public API.
为了更好地支持内省,模块应使用该 __all__
属性在其公共 API 中显式声明名称。设置为 __all__
空列表表示该模块没有公共 API。
Even with __all__
set appropriately, internal interfaces (packages, modules, classes, functions, attributes or other names) should still be prefixed with a single leading underscore.
即使 __all__
设置得当,内部接口(包、模块、类、函数、属性或其他名称)仍应以单个前导下划线为前缀。
An interface is also considered internal if any containing namespace (package, module or class) is considered internal.
如果任何包含命名空间(包、模块或类)被视为内部接口,则接口也被视为内部接口。
Imported names should always be considered an implementation detail. Other modules must not rely on indirect access to such imported names unless they are an explicitly documented part of the containing module’s API, such as os.path
or a package’s __init__
module that exposes functionality from submodules.
导入的名称应始终被视为实现细节。其他模块不得依赖于对此类导入名称的间接访问,除非它们是包含模块的 API 的显式记录部分,例如 os.path
或公开子模块功能的包 __init__
模块。
Programming Recommendations编程建议
- Code should be written in a way that does not disadvantage other implementations of Python (PyPy, Jython, IronPython, Cython, Psyco, and such).
代码的编写方式不应不利于其他 Python 实现(PyPy、Jython、IronPython、Cython、Psyco 等)。For example, do not rely on CPython’s efficient implementation of in-place string concatenation for statements in the form
a += b
ora = a + b
. This optimization is fragile even in CPython (it only works for some types) and isn’t present at all in implementations that don’t use refcounting. In performance sensitive parts of the library, the''.join()
form should be used instead. This will ensure that concatenation occurs in linear time across various implementations.
例如,不要依赖 CPython 对 ora = a + b
形式的a += b
语句进行就地字符串连接的有效实现。即使在 CPython 中,这种优化也很脆弱(它仅适用于某些类型),并且在不使用 refcounting 的实现中根本不存在。在库的性能敏感部分,应改用表单''.join()
。这将确保在各种实现中以线性时间发生串联。 - Comparisons to singletons like None should always be done with
is
oris not
, never the equality operators.
与像 None 这样的单例的比较应该始终使用is
或is not
,而不是相等运算符。Also, beware of writing
if x
when you really meanif x is not None
– e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!
另外,当你真正想if x is not None
写if x
的时候,要小心——例如,在测试默认为 None 的变量或参数是否设置为其他值时。另一个值的类型(如容器)在布尔上下文中可能为 false! - Use
is not
operator rather thannot ... is
. While both expressions are functionally identical, the former is more readable and preferred:
使用is not
运算符而不是not ... is
.虽然这两种表达式在功能上相同,但前者更具可读性和首选性:# Correct: if foo is not None:
# Wrong: if not foo is None:
- When implementing ordering operations with rich comparisons, it is best to implement all six operations (
__eq__
,__ne__
,__lt__
,__le__
,__gt__
,__ge__
) rather than relying on other code to only exercise a particular comparison.
在实现具有丰富比较的排序操作时,最好实现所有六个操作(__eq__
、 、 、 、__ne__
__lt__
__le__
__gt__
),__ge__
而不是依赖其他代码来仅执行特定的比较。To minimize the effort involved, the
functools.total_ordering()
decorator provides a tool to generate missing comparison methods.
为了最大程度地减少所涉及的工作量,修functools.total_ordering()
饰器提供了一个工具来生成缺失的比较方法。PEP 207 indicates that reflexivity rules are assumed by Python. Thus, the interpreter may swap
y > x
withx < y
,y >= x
withx <= y
, and may swap the arguments ofx == y
andx != y
. Thesort()
andmin()
operations are guaranteed to use the<
operator and themax()
function uses the>
operator. However, it is best to implement all six operations so that confusion doesn’t arise in other contexts.
PEP 207 表示 Python 假定了自反性规则。因此,解释器可以y > x
用x < y
、y >= x
和 交换,并且可以交换x == y
和x != y
x <= y
的参数。sort()
保证 andmin()
操作使用运算符,max()
函数使用>
<
运算符。但是,最好实现所有六个操作,以免在其他上下文中出现混淆。 - Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier:
始终使用 def 语句,而不是将 lambda 表达式直接绑定到标识符的赋值语句:# Correct: def f(x): return 2*x
# Wrong: f = lambda x: 2*x
The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘<lambda>’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)
第一种形式意味着生成的函数对象的名称是专门的“f”,而不是泛型的“”。这通常对于回溯和字符串表示形式更有用。赋值语句的使用消除了 lambda 表达式相对于显式 def 语句所能提供的唯一好处(即它可以嵌入到更大的表达式中) - Derive exceptions from
Exception
rather thanBaseException
. Direct inheritance fromBaseException
is reserved for exceptions where catching them is almost always the wrong thing to do.
派生异常,Exception
而不是BaseException
。直接继承 fromBaseException
保留给异常,在这些异常中,捕获它们几乎总是错误的做法。Design exception hierarchies based on the distinctions that code catching the exceptions is likely to need, rather than the locations where the exceptions are raised. Aim to answer the question “What went wrong?” programmatically, rather than only stating that “A problem occurred” (see PEP 3151 for an example of this lesson being learned for the builtin exception hierarchy)
根据捕获异常的代码可能需要的区别(而不是引发异常的位置)来设计异常层次结构。旨在以编程方式回答“出了什么问题?”,而不是仅仅说明“发生了问题”(请参阅 PEP 3151,了解针对内置异常层次结构学习的本课示例)Class naming conventions apply here, although you should add the suffix “Error” to your exception classes if the exception is an error. Non-error exceptions that are used for non-local flow control or other forms of signaling need no special suffix.
类命名约定在这里适用,但如果异常是错误,则应将后缀“Error”添加到异常类中。用于非本地流控制或其他形式的信令的非错误异常不需要特殊后缀。 - Use exception chaining appropriately.
raise X from Y
should be used to indicate explicit replacement without losing the original traceback.
适当地使用异常链接。raise X from Y
应该用于指示显式替换,而不会丢失原始回溯。When deliberately replacing an inner exception (using
raise X from None
), ensure that relevant details are transferred to the new exception (such as preserving the attribute name when converting KeyError to AttributeError, or embedding the text of the original exception in the new exception message).
当有意替换内部异常 (usingraise X from None
) 时,请确保将相关详细信息传输到新异常(例如,在将 KeyError 转换为 AttributeError 时保留属性名称,或在新的异常消息中嵌入原始异常的文本)。 - When catching exceptions, mention specific exceptions whenever possible instead of using a bare
except:
clause:
捕获异常时,请尽可能提及特定的异常,而不是使用裸except:
子句:try: import platform_specific_module except ImportError: platform_specific_module = None
A bare
except:
clause will catch SystemExit and KeyboardInterrupt exceptions, making it harder to interrupt a program with Control-C, and can disguise other problems. If you want to catch all exceptions that signal program errors, useexcept Exception:
(bare except is equivalent toexcept BaseException:
).
裸except:
子句将捕获 SystemExit 和 KeyboardInterrupt 异常,从而更难使用 Control-C 中断程序,并可能掩盖其他问题。如果要捕获所有表示程序错误的异常,请使用except Exception:
(bare except 等效于except BaseException:
)。A good rule of thumb is to limit use of bare ‘except’ clauses to two cases:
一个好的经验法则是将裸露的“例外”子句的使用限制在两种情况下:- If the exception handler will be printing out or logging the traceback; at least the user will be aware that an error has occurred.
如果异常处理程序将打印或记录回溯;至少用户会知道发生了错误。 - If the code needs to do some cleanup work, but then lets the exception propagate upwards with
raise
.try...finally
can be a better way to handle this case.
如果代码需要执行一些清理工作,但随后让异常向raise
上传播。try...finally
可能是处理这种情况的更好方法。
- If the exception handler will be printing out or logging the traceback; at least the user will be aware that an error has occurred.
- When catching operating system errors, prefer the explicit exception hierarchy introduced in Python 3.3 over introspection of
errno
values.
捕获操作系统错误时,首选 Python 3.3 中引入的显式异常层次结构,而不是errno
自省值。 - Additionally, for all try/except clauses, limit the
try
clause to the absolute minimum amount of code necessary. Again, this avoids masking bugs:
此外,对于所有 try/except 子句,将该try
子句限制为所需的绝对最小代码量。同样,这避免了屏蔽错误:# Correct: try: value = collection[key] except KeyError: return key_not_found(key) else: return handle_value(value)
# Wrong: try: # Too broad! return handle_value(collection[key]) except KeyError: # Will also catch KeyError raised by handle_value() return key_not_found(key)
- When a resource is local to a particular section of code, use a
with
statement to ensure it is cleaned up promptly and reliably after use. A try/finally statement is also acceptable.
当资源是特定代码段的本地资源时,请使用with
语句来确保在使用后及时可靠地清理它。try/finally 语句也是可以接受的。 - Context managers should be invoked through separate functions or methods whenever they do something other than acquire and release resources:
每当上下文管理器执行除获取和释放资源之外的操作时,都应通过单独的函数或方法调用它们:# Correct: with conn.begin_transaction(): do_stuff_in_transaction(conn)
# Wrong: with conn: do_stuff_in_transaction(conn)
The latter example doesn’t provide any information to indicate that the
__enter__
and__exit__
methods are doing something other than closing the connection after a transaction. Being explicit is important in this case.
后一个示例不提供任何信息来指示__enter__
and__exit__
方法在事务后关闭连接以外的其他操作。在这种情况下,明确是很重要的。 - Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as
return None
, and an explicit return statement should be present at the end of the function (if reachable):
在 return 语句中保持一致。函数中的所有 return 语句都应返回表达式,或者它们都不应返回。如果任何 return 语句返回一个表达式,则任何未返回值的 return 语句都应将其显式声明为return None
,并且应在函数末尾显示显式 return 语句(如果可访问):# Correct: def foo(x): if x >= 0: return math.sqrt(x) else: return None def bar(x): if x < 0: return None return math.sqrt(x)
# Wrong: def foo(x): if x >= 0: return math.sqrt(x) def bar(x): if x < 0: return return math.sqrt(x)
- Use
''.startswith()
and''.endswith()
instead of string slicing to check for prefixes or suffixes.
使用''.startswith()
and''.endswith()
代替字符串切片来检查前缀或后缀。startswith() and endswith() are cleaner and less error prone:
startswith() 和 endswith() 更简洁,更不容易出错:# Correct: if foo.startswith('bar'):
# Wrong: if foo[:3] == 'bar':
- Object type comparisons should always use isinstance() instead of comparing types directly:
对象类型比较应始终使用 isinstance() 而不是直接比较类型:# Correct: if isinstance(obj, int):
# Wrong: if type(obj) is type(1):
- For sequences, (strings, lists, tuples), use the fact that empty sequences are false:
对于序列(字符串、列表、元组),请使用空序列为 false 的事实:# Correct: if not seq: if seq:
# Wrong: if len(seq): if not len(seq):
- Don’t write string literals that rely on significant trailing whitespace. Such trailing whitespace is visually indistinguishable and some editors (or more recently, reindent.py) will trim them.
不要编写依赖于大量尾随空格的字符串文本。这种尾随的空格在视觉上是无法区分的,一些编辑器(或最近的 reindent.py)会修剪它们。 - Don’t compare boolean values to True or False using
==
:
不要使用以下命令==
将布尔值与 True 或 False 进行比较:# Correct: if greeting:
# Wrong: if greeting == True:
Worse: 更 糟:
# Wrong: if greeting is True:
- Use of the flow control statements
return
/break
/continue
within the finally suite of atry...finally
, where the flow control statement would jump outside the finally suite, is discouraged. This is because such statements will implicitly cancel any active exception that is propagating through the finally suite:
不建议在 atry...finally
的 finally 套件中使用流控制语句 / /break
continue
,其中流控制语句return
会跳到 finally 套件之外。这是因为此类语句将隐式取消通过 finally 套件传播的任何活动异常:# Wrong: def foo(): try: 1 / 0 finally: return 42
Function Annotations 函数注解
With the acceptance of PEP 484, the style rules for function annotations have changed.
随着 PEP 484 的接受,函数注解的样式规则发生了变化。
- Function annotations should use PEP 484 syntax (there are some formatting recommendations for annotations in the previous section).
函数注解应使用 PEP 484 语法(上一节中有一些注释的格式建议)。 - The experimentation with annotation styles that was recommended previously in this PEP is no longer encouraged.
不再鼓励在此 PEP 中推荐的注释样式的试验。 - However, outside the stdlib, experiments within the rules of PEP 484 are now encouraged. For example, marking up a large third party library or application with PEP 484 style type annotations, reviewing how easy it was to add those annotations, and observing whether their presence increases code understandability.
然而,在 stdlib 之外,现在鼓励在 PEP 484 规则内进行实验。例如,使用 PEP 484 样式类型注释标记大型第三方库或应用程序,查看添加这些注释的难易程度,并观察它们的存在是否提高了代码的可理解性。 - The Python standard library should be conservative in adopting such annotations, but their use is allowed for new code and for big refactorings.
Python 标准库在采用此类注解时应该保守,但允许将它们用于新代码和大型重构。 - For code that wants to make a different use of function annotations it is recommended to put a comment of the form:
对于想要不同使用函数注解的代码,建议放置以下形式的注释:# type: ignore
near the top of the file; this tells type checkers to ignore all annotations. (More fine-grained ways of disabling complaints from type checkers can be found in PEP 484.)
靠近文件顶部;这会告诉类型检查器忽略所有注释。(禁用类型检查器投诉的更细粒度方法可在 PEP 484 中找到。 - Like linters, type checkers are optional, separate tools. Python interpreters by default should not issue any messages due to type checking and should not alter their behavior based on annotations.
与 linter 一样,类型检查器是可选的独立工具。默认情况下,Python 解释器不应由于类型检查而发出任何消息,也不应根据注释更改其行为。 - Users who don’t want to use type checkers are free to ignore them. However, it is expected that users of third party library packages may want to run type checkers over those packages. For this purpose PEP 484 recommends the use of stub files: .pyi files that are read by the type checker in preference of the corresponding .py files. Stub files can be distributed with a library, or separately (with the library author’s permission) through the typeshed repo [5].
不想使用类型检查器的用户可以自由地忽略它们。但是,预计第三方库包的用户可能希望对这些包运行类型检查器。为此,PEP 484 建议使用存根文件:由类型检查器优先于相应的 .py 文件读取的 .pyi 文件。存根文件可以与库一起分发,也可以通过 typeshed repo [5] 单独分发(在库作者的许可下)。
Variable Annotations 变量注释
PEP 526 introduced variable annotations. The style recommendations for them are similar to those on function annotations described above:
PEP 526 引入了变量注释。它们的样式建议与上面描述的函数注释类似:
- Annotations for module level variables, class and instance variables, and local variables should have a single space after the colon.
模块级变量、类和实例变量以及局部变量的注释在冒号后应有一个空格。 - There should be no space before the colon.
冒号前不应有空格。 - If an assignment has a right hand side, then the equality sign should have exactly one space on both sides:
如果赋值的右侧,则等号的两侧应该只有一个空格:# Correct: code: int class Point: coords: Tuple[int, int] label: str = '<unknown>'
# Wrong: code:int # No space after colon code : int # Space before colon class Test: result: int=0 # No spaces around equality sign
- Although the PEP 526 is accepted for Python 3.6, the variable annotation syntax is the preferred syntax for stub files on all versions of Python (see PEP 484 for details).
尽管 Python 3.6 接受 PEP 526,但变量注释语法是所有 Python 版本上存根文件的首选语法(有关详细信息,请参阅 PEP 484)。
Footnotes 脚注
[1]
Hanging indentation is a type-setting style where all the lines in a paragraph are indented except the first line. In the context of Python, the term is used to describe a style where the opening parenthesis of a parenthesized statement is the last non-whitespace character of the line, with subsequent lines being indented until the closing parenthesis.
悬挂缩进是一种排版样式,其中段落中的所有行都缩进,但第一行除外。在 Python 的上下文中,该术语用于描述一种样式,其中带括号的语句的左括号是该行的最后一个非空格字符,后续行缩进直到右括号。