Python代码规范pep8

Author: Guido van Rossum , Barry Warsaw , Alyssa Coghlan

Status: Active

Type: Process

Created: 05-Jul-2001

Post-History: 05-Jul-2001, 01-Aug-2013

Introduction|简介

这份文档为主Python发行版中规范库的Python代码供给了编码规范。请参阅相关的信息性PEP,该PEP描绘了Python C完成中的C代码的款式攻略

这份文档和PEP 257(文档字符串规范)改编自Guido的原始Python款式攻略文章,并加入了Barry款式攻略的一些内容[2]

跟着额定的约好的发现和语言自身的改变使过去的约好变得过期,这个款式攻略会跟着时间的推移而演化。

许多项目都有自己的编码风格攻略。在任何抵触的状况下,项目特定的攻略优先适用于该项目。

A Foolish Consistency is the Hobgoblin of Little Minds |愚笨的一贯性是小心灵的小妖精

Guido的一个要害洞察是代码被阅读的频率远远超过它被编写的次数。这儿供给的原则旨在进步代码的可读性,并使其在广泛的Python代码范围内坚持共同。正如PEP 20Python之禅所说:“可读性很重要”。

import this
"""
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
"""
"""
美胜过丑恶。
明晰胜过隐晦。
简略胜过杂乱。
杂乱胜过繁琐。
扁平胜过嵌套。
疏松胜过密布。
可读性很重要。
特别状况并不足以打破规矩。
虽然实用性胜过朴实性。
过错永久不应该悄悄地过去。
除非明晰缄默沉静。
面临不确认性,回绝猜测的诱惑。
应该有一种显着的办法来做事,最好只要一种。
虽然这种办法一开端或许不显着,除非你是荷兰人(指Python的创作者Guido van Rossum,他是荷兰人)。
现在胜过永久不做。
虽然从不做一般比当即去做好。
假如完成很难解说,那是一个坏主意。
假如完成简略解说,那或许是个好主意。
命名空间是一个绝妙的主意 - 让我们做更多这样的作业!
"""

款式攻略关乎共同性。与这个款式攻略坚持共同是重要的。项目内的共同性更为重要。在一个模块或函数内的共同性是最重要的。

可是,要知道何时要有所不共同 – 有时款式攻略的主张并不适用。当有疑虑时,请运用您的最佳判别力。查看其他示例并决议哪种看起来最好。而且不要犹疑询问!

特别是:不要为了遵从这个PEP而损坏向后兼容性

忽略特定攻略的一些好理由包括:

  • 当运用该攻略会使代码关于习气于阅读遵从这个PEP的代码的人来说变得更不可读时。
  • 为了与周围的代码坚持共同,而周围的代码也违反了它(也许是由于前史原因) – 虽然这也是整理其他人犯下的过错的时机(真正的XP风格)。
  • 由于所讨论的代码在该攻略引进之前就存在,而且修正该代码没有其他原因。
  • 当代码需求坚持与不支撑款式攻略主张的功用的较旧版别的Python兼容时。

Code Lay-out|代码布局

Indentation|缩进

运用每个缩进等级4个空格。

接连行应该运用笔直对齐括号、方括号和花括号内的元素,可以运用Python的括号内隐式行连接,也可以运用悬挂缩进 [1]。运用悬挂缩进时,应考虑以下事项:榜首行不应有参数,而且应运用进一步的缩进明晰地标明它是一行的延续

# 正确:
# 与开端分隔符对齐
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)

4个空格的规矩在接连行中是可选的。

可选:

# 悬挂缩进可以缩进到除了4个空格之外的其他方位
foo = long_function_name(
  var_one, var_two,
  var_three, var_four)

当if句子的条件部分满足长,需求跨多行编写时,值得留意的是,两个字符的要害字(即 if),加上一个空格,再加上一个开括号,会为多行条件的后续行创立一个天然的4个空格缩进。这或许会在if句子内嵌的缩进代码块的可视上产生抵触,后者也会天然地缩进到4个空格。这个PEP对怎么(或是否)进一步在视觉上差异这样的条件行与if句子内嵌的代码块采取了明晰的立场。在这种状况下可以承受的选项包括但不限于:

# 不需求额定的缩进
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()

多行结构的闭括号/方括号/括号可以与列表的最终一行的榜首个非空格字符对齐,如下所示:

my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

Tabs or Spaces|制表符仍是空格

空格是首选的缩进办法。 制表符应仅用于与已运用制表符缩进的代码坚持共同。 Python 不答应混合制表符和空格进行缩进

Maximum Line Length|最大代码行长度

约束一切行的最大长度为79个字符

关于较少结构约束的长文本块(例如文档字符串或注释),行长度应约束为72个字符

约束所需的编辑器窗口宽度可以使多个文件并排翻开,并在运用代码审查东西时体现杰出,这些东西将两个版别呈现在相邻的列中。

大多数东西中的默认换行损坏了代码的视觉结构,使其更难了解。这些约束的挑选是为了防止在将窗口宽度设置为80的编辑器中换行,即便东西在换行时在最终一列放置符号符号。有些依据Web的东西或许底子不供给动态换行。

一些团队更喜欢更长的行长度。关于由可以就此问题达成共同的团队专门或首要维护的代码,可以将行长度约束进步到99个字符,前提是注释和文档字符串依然在72个字符处换行

Python规范库保守并要求将行约束为79个字符(将文档字符串/注释约束为72个字符)。

首选的长行换行办法是运用Python在括号、方括号和大括号内隐式的行接连。可以经过在括号内包装表达式来将长行分红多行。这应该优先于运用反斜杠进行行接连。

反斜杠在某些状况下依然是恰当的。例如,在Python 3.10之前,长的多个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())

Should a Line Break Before or After a Binary Operator|应该在二元运算符之前仍是之后换行

几十年来,引荐的风格是在二元运算符之后换行。但这样做或许会影响可读性,有两方面的原因:运算符往往涣散在屏幕上的不同列,而且每个运算符都移动到其操作数的前一行。在这儿,眼睛需求额定的作业来判别哪些项目是相加的,哪些是相减的:

# 过错:
# 运算符远离操作数
income = (gross_wages  
          taxable_interest  
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

为了解决这个可读性问题,数学家及其出版商遵从相反的约好。唐纳德克努斯在他的《计算机排版》系列中解说了传统规矩:“虽然段落内的公式总是在二元运算符和关系之后换行,但显示的公式总是在二元运算符之前换行[3]

遵从数学传统一般会产生更易读的代码:

# 正确
# 易于将运算符与操作数匹配
income = (gross_wages
            taxable_interest
            (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

在 Python 代码中,只要约好在本地共同,就答应在二元运算符之前或之后中止。关于新代码,主张选用 Knuth 风格。

Blank Lines|空白行

在顶层函数和类界说之间留两个空行

类内的办法界说周围留有一行空行

可以适度运用额定的空行来分隔相关函数的组。在一组相关的一行函数之间可以省掉空行(例如一组虚拟完成)。

在函数中,适度地运用空行标明逻辑部分。

Python将操控-L(即^L)换页符视为空白字符;许多东西将这些字符视为分页符,因而可以运用它们来分隔文件中相关部分的页面。请留意,一些编辑器和依据Web的代码查看器或许无法将操控-L辨以为换页符,并将显示其方位的另一字符。

# 顶层函数之间的两个空行
def function1():
    pass
def function2():
    pass
# 两个空行分隔顶层函数和类界说
class MyClass:
    # 类内办法之间的一个空行
    def method1(self):
        pass
    def method2(self):
        pass
# 额定的空行分隔相关函数组
def related_function1():
    pass
def related_function2():
    pass
# 函数内逻辑部分运用适度的空行
def complex_function():
    # 逻辑部分1
    x = 1
    y = 2
    # 空行分隔逻辑部分
    result = x   y
    # 逻辑部分2
    return result

Source File Encoding|源文件编码

核心Python发行版中的代码应一直运用UTF-8,而且不应具有编码声明

在规范库中,仅应出于测试目的运用非UTF-8编码。请慎重运用非ASCII字符,最好仅用于标明地址和人名。假如将非ASCII字符用作数据,请防止喧闹的Unicode字符,例如zalgo和字节顺序符号。

Python规范库中的一切标识符有必要仅运用ASCII标识符,而且在可行的状况下应运用英语单词(在许多状况下,运用了不是英语的缩写和技术术语)。

鼓舞全球受众的开源项目选用相似的政策。

Import|引进

  • 导入一般应该放在独自的行上:
# Correct:
import os
import sys
# Wrong:
import sys, os
# Correct:
from subprocess import Popen, PIPE
  • 导入总是放在文件顶部,紧接着任何模块注释和文档字符串之后,而在模块全局变量和常量之前。导入应依照以下顺序分组:

    • 规范库导入
    • 相关的第三方导入
    • 本地运用/库特定导入

在每组导入之间应该留有一行空行。

# 规范库导入
import os
import sys
# 第三方库导入
import requests
from flask import Flask
# 本地运用/库导入
from myapp import utils
from myapp.models import User
# 模块全局变量
MY_CONSTANT = 42
# 函数界说等其他代码...
  • 主张运用肯定导入,由于它们一般更易读,而且假如导入体系配置过错(例如,包内的目录出现在 sys.path 中时),它们一般体现得更好(或许至少供给更好的过错音讯):
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example

可是,相对导入也是肯定导入的可承受代替计划,特别是在处理杂乱的包布局时,其中运用肯定导入会显得不必要冗长:

from . import sibling
from .sibling import example

规范库代码应防止杂乱的包布局并一直运用肯定导入

  • 从包括类的模块中导入类时,一般可以这样书写:
from myclass import MyClass
from foo.bar.yourclass import YourClass

假如这种拼写导致本地称号抵触,请明晰拼写它们:

import myclass
import foo.bar.yourclass

后续运用myclass.MyClassfoo.bar.yourclass.YourClass

  • 应防止运用通配符导入(from import *),由于它们会使命名空间中存在哪些称号变得不明晰,既会困扰读者,也会困扰许多主动化东西。通配符导入有一种可以辩解的用例,即将内部接口作为公共API的一部分从头发布(例如,用加速模块的界说覆盖纯Python完成的接口,事前不知道哪些界说将被覆盖)。以这种办法从头发布称号时,依然适用以下关于公共接口和内部接口的原则。

Module Level Dunder Names|模块等级的双下划线命名

模块等级的“dunders”(即具有两个前导和两个跟随下划线的称号),例如__all____author____version__等,应该放在模块docstring之后,但在除了__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

String Quotes|字符串引号

在Python中,单引号和双引号括起来的字符串是相同的。PEP 8并未就此提出主张。挑选一种规矩并坚持运用它。可是,当字符串包括单引号或双引号字符时,主张运用另一种引号,以防止在字符串中运用反斜杠,这有助于进步可读性

关于三引号括起来的字符串,一直运用双引号字符,以坚持与PEP 257中文档字符串约好的共同性。

One-line Doctrings| 一行文档字符串

单行代码应该是十分显着和简略的状况。它们真的应该合适一行,例如:

def kos_root():
    """Return the pathname of the KOS root directory."""
    global _kos_root
    if _kos_root: return _kos_root
    ...

留意:

  • 即便字符串合适一行,也运用三重引号。这样可以便利今后扩展它。

  • 完毕引号与开端引号在同一行。这在一行中看起来更好。

  • 在文档字符串之前或之后都没有空行。

  • 文档字符串是一个以句点完毕的短语。它规矩了函数或办法的作用作为命令(“履行这个”,“回来那个”),而不是作为描绘;例如,不要写“回来路径名…”。

  • 单行文档字符串不应该是“签名”,重申函数/办法的参数(可以经过内省获取)。不要这样做:

    def function(a, b):
        """function(a, b) -> list"""
    

    这种类型的文档字符串只适用于C函数(如内置函数),其中无法进行内省。可是,经过内省无法确认回来值的性质,因而应该说到。关于这样的文档字符串,首选办法或许是:

    def function(a, b):
        """Do X and return a list."""
    

Multi-line Docstrings|多行文档字符串

多行文档字符串包括一行摘要,就像单行文档字符串一样,后跟一行空行,然后是更具体的描绘。摘要行或许会被主动索引东西运用;重要的是它合适在一行上,而且与文档字符串的其余部分由一行空行分隔。摘要行可以与最初引号坐落同一行,也可以在下一行。整个文档字符串的缩进与其榜首行的引号相同。

在一切记载类的文档字符串(单行或多行)之后刺进一行空行 – 一般来说,类的办法彼此之间由单个空行分隔,而且文档字符串需求与榜首个办法经过一行空行分隔。

脚本(独立程序)的文档字符串应该可用作其“用法”音讯,在以不正确或短少参数调用脚本时打印此音讯(或许运用“-h”选项,标明“协助”)。这样的文档字符串应该记载脚本的功用和命令行语法、环境变量和文件。用法音讯可以适当具体(几屏幕),应满足供新用户正确运用命令,以及关于娴熟用户来说是一切选项和参数的完好快速参阅。

模块的文档字符串一般应列出由模块导出的类、反常和函数(以及任何其他目标),每个目标都有一行摘要。(这些摘要一般比目标文档字符串中的摘要行供给更少的细节。)包的文档字符串(即包的__init__.py模块的文档字符串)还应列出由包导出的模块和子包。

函数或办法的文档字符串应概述其行为并记载其参数、回来值、副作用、引发的反常以及调用时的约束(假如适用)。应标明可选参数。文档字符串应说明要害字参数是否是接口的一部分。

类的文档字符串应概述其行为并列出公共办法和实例变量。假如类目的被子类化,而且有一个供子类运用的附加接口,这个接口应该独自列在文档字符串中。类的构造函数应该在其__init__办法的文档字符串中记载。各个办法应该由各自的文档字符串记载。

假如一个类是另一个类的子类,而且其行为首要承继自那个类,其文档字符串应说到这一点,并概述两者之间的差异。运用动词“override”标明子类办法替换了超类办法而且不调用超类办法;运用动词“extend”标明子类办法调用超类办法(除了自己的行为)。

不要运用Emacs的约好,即在运行文本中将函数或办法的参数写成大写。Python差异大小写,参数名可用于要害字参数,因而文档字符串应记载正确的参数名。最好在独自的行上列出每个参数。例如:

def complex(real=0.0, imag=0.0):
    """Form a complex number.
    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    ...
class ExampleClass:
    """This is a brief summary of what the class does.
    Public Methods:
    - public_method1: Explanation of public_method1.
    - public_method2: Explanation of public_method2.
    Instance Variables:
    - instance_var1: Explanation of instance_var1.
    - instance_var2: Explanation of instance_var2.
    Public Subclass Interface:
    - subclass_method: Explanation of subclass_method.
    """
    def __init__(self, arg1, arg2, kwarg1='default'):
        """This is a brief summary of what the constructor does.
        Parameters:
        - arg1: Explanation of arg1.
        - arg2: Explanation of arg2.
        - kwarg1 (optional): Explanation of kwarg1, which has a default value.
        """
        # Constructor implementation here
    def public_method1(self, param):
        """This is a brief summary of what public_method1 does.
        Parameters:
        - param: Explanation of param.
        Returns:
        Explanation of the return value.
        """
        # Method implementation here
    def public_method2(self):
        """This is a brief summary of what public_method2 does.
        Returns:
        Explanation of the return value.
        """
        # Method implementation here

Handling Docstring Indentation|处理文档字符串缩进

文档字符串处理东西将从文档字符串的第二行及今后的一切行中剥离一个统一的缩进,该缩进等于榜首行之后一切非空行的最小缩进。文档字符串的榜首行(即直到榜首个换行符之前)中的任何缩进都是无关紧要的并将被移除。保存文档字符串后续行的相对缩进。应该从文档字符串的最初和结尾删去空行。

def trim(docstring):
    if not docstring:
        return ''
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = sys.maxsize
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < sys.maxsize:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    # Strip off trailing and leading blank lines:
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    # Return a single string:
    return 'n'.join(trimmed)

在这个示例中,文档字符串包括两个换行符,因而有 3 行长。榜首行和最终一行是空行:

def foo():
    """
    This is the second line of the docstring.
    """
>>> print repr(foo.__doc__)
'n    This is the second line of the docstring.n    '
>>> foo.__doc__.splitlines()
['', '    This is the second line of the docstring.', '    ']
>>> trim(foo.__doc__)
'This is the second line of the docstring.'

Whitespace in Expressions and Statements|表达式和句子中的空格

Pet Peeves|令人讨厌的代码习气

  • 在以下状况下防止运用剩余的空格:
# Correct:
spam(ham[1], {eggs: 2})
# Wrong:
spam( ham[ 1 ], { eggs: 2 } )
  • 在跟随逗号和后边的右括号之间:
# Correct:
foo = (0,)
# Wrong:
bar = (0, )
  • 紧接在逗号、分号或冒号之前:
# Correct:
if x == 4: print(x, y); x, y = y, x
# Wrong:
if x == 4 : print(x , y) ; x , y = y , x
  • 可是,在切片中,冒号的作用相似于二进制运算符,应该在两边具有相等的空格量(将其视为优先级最低的运算符)。在扩展切片中,两个冒号有必要运用相同数量的空格。例外状况:当省掉切片参数时,空格也会被省掉
# 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]
  • 紧接在开端函数调用的参数列表的左括号之前:
# Correct:
spam(1)
# Wrong:
spam (1)
  • 紧接在开端索引或切片的左括号之前:
# Correct:
dct['key'] = lst[index]
# Wrong:
dct ['key'] = lst [index]
  • 在赋值(或其他)运算符周围运用多个空格,以使其与另一个对齐
# Correct:
x = 1
y = 2
long_variable = 3
# Wrong:
x             = 1
y             = 2
long_variable = 3

Other Recommendations|其他引荐

  • 防止在任何地方留下跟随的空格。由于它一般是看不见的,所以或许会引起混杂:例如,反斜杠后边跟着一个空格和一个换行符不算作行接连符号。有些编辑器不会保存它,而且许多项目(如CPython自身)都有预提交挂钩来回绝它。
  • 一直在这些二进制运算符的两边各用一个空格包围:赋值(=),增强赋值( =,-=等),比较(==,<,>,!=,<>,<=,>=,in,not in,is,is not),布尔值(and,or,not)。
  • 假如运用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围增加空格。请依据自己的判别力行事;可是,永久不要运用多个空格,而且在二进制运算符的两边一直具有相同数量的空格
# 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)
  • 函数注释应该运用冒号的正常规矩,而且假如存在 -> 箭头,则一直在其周围加上空格。 (有关函数注释的更多信息,请参见下面的“函数注释”:
# Correct:
def munge(input: AnyStr): ...
def munge() -> PosInt: ...
# Wrong:
def munge(input:AnyStr): ...
def munge()->PosInt: ...
  • 在用于指示要害字参数或用于指示未注释的函数参数的默认值时,不要在 = 符号周围运用空格:
# 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)

可是,在将参数注释与默认值结合运用时,在 = 符号周围运用空格

# 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): ...
  • 复合句子(同一行上的多个句子)一般是不鼓舞的
# Correct:
if foo == 'blah':
    do_blah_thing()
do_one()
do_two()
do_three()
# Wrong:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
  • 虽然有时将具有小主体的 if/for/while 句子放在同一行上是可以的,但永久不要对多子句句子这样做。还要防止折叠这样的长行!
# Wrong:
if foo == 'blah': do_blah_thing()
for x in lst: total  = x
while t < 10: t = delay()
# 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|何时运用跟随逗号

跟随逗号一般是可选的,但当创立一个只要一个元素的元组时是强制的。为了明晰起见,主张将后者括在(从技术上讲是剩余的)括号中:

# Correct:
FILES = ('setup.cfg',)
# Wrong:
FILES = 'setup.cfg',

当跟随逗号是剩余的时分,一般在运用版别操控体系时很有协助,当估计随时间推移将扩展值、参数或导入项的列表。模式是将每个值(等等)独自放在一行上,一直增加跟随逗号,并在下一行增加右括号/方括号/大括号。可是,在与封闭定界符相同的行上放置跟随逗号是没有意义的(除了上述单例元组的状况):

# Correct:
FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )
# Wrong:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

Comments|注释

与代码相矛盾的注释比没有注释更糟糕。一直优先保证在代码更改时使注释坚持最新!

注释应该是完好的句子。榜首个单词应大写,除非它是以小写字母最初的标识符(永久不要更改标识符的大小写!)。

块注释一般由一个或多个段落组成,由完好的句子构建,每个句子以句点完毕

在多句注释中,除了最终一句之外,句子完毕后应运用一个或两个空格。

保证您的注释对运用您所编写的语言的其他人来说是明晰且简略了解的。

非英语国家的Python编码人员:请用英语编写您的注释,除非您百分之百确认代码永久不会被不明白您语言的人阅读。

Block Comments|块注释

块注释一般适用于其后的一些(或一切)代码,并缩进到与该代码相同的等级。块注释的每一行都以“#”和一个空格最初(除非它是注释内的缩进文本)。

块注释内的段落由包括单个“#”的行分隔。

# This is a block comment
# It applies to the following code block
# Each line starts with "#" and a space
# First paragraph of the comment
# providing additional context.
# Second paragraph with more details.
# Each paragraph is separated by a line starting with "#".
code_here = 42

Inline Comments|内联注释

慎重运用内联注释。

内联注释是与句子坐落同一行的注释。内联注释应与句子至少相隔两个空格。它们应以“#”和一个空格最初。

假如内联注释陈说了显而易见的现实,则它们是不必要的,实际上是涣散留意力的。不要这样做:

x = x   1                 # Increment x
x = x   1                 # Compensate for border

Documentation Strings|文档字符串

编写杰出文档字符串(即“docstrings”)的规范被概括在 PEP 257 中。

  • 为一切公共模块、函数、类和办法编写文档字符串。关于非公共办法,文档字符串并非必需,但您应该有一条注释来描绘该办法的功用。这条注释应该出现在 def 行之后。
  • PEP 257 描绘了杰出的文档字符串约好。请留意,最重要的是,完毕多行文档字符串的 “”” 应该独自坐落一行上:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
  • 关于一行文档字符串,请保证封闭 “”” 坐落同一行上:
"""Return an ex-parrot."""

Naming Conventions|命名约好

Python库的命名规范有些紊乱,因而永久无法完全坚持共同。虽然如此,以下是现在引荐的命名规范。新模块和包(包括第三方框架)应依照这些规范编写,但假如现有库选用不同的风格,更倾向于坚持内部共同性。

Overriding Principle|压到一切的原则

用户可见的作为 API 公共部分的称号应遵从反映用法而不是完成的约好。

在 Python 中,当界说作为公共 API(运用程序编程接口)一部分的称号(例如变量、函数、类等)时,遵从反映用户怎么与这些称号交互的约好至关重要。这种做法可以保证明晰度、共同性,并为运用您的代码的开发人员供给更好的体会。 例如,假如您正在规划一个将成为公共 API 一部分的类,请挑选一个可以向开发人员清楚传达其目的和用法的称号。该称号应该在其预期用处的上下文中有意义,而且应该遵从既定的约好,以在 Python 代码库中坚持规范款式。

Descriptive: Naming Styles|描绘性:命名风格

有许多不同的命名风格。可以独立于其用处辨认运用了哪种命名风格将会很有协助。

以下是常见的命名风格:

  • b(单个小写字母)
  • B(单个大写字母)
  • lowercase(小写字母)
  • lower_case_with_underscores(下划线分隔的小写字母)
  • UPPERCASE(大写字母)
  • UPPER_CASE_WITH_UNDERSCORES(下划线分隔的大写字母)
  • CapitalizedWords(或CapWords,或CamelCase,由于其字母看起来有点崎岖[4])。这有时也被称为StudlyCaps。 留意:在CapWords中运用首字母缩写时,请将缩写的一切字母都大写。因而,HTTPServerError比HttpServerError更好。
  • mixedCase(与CapitalizedWords不同之处在于以小写字母最初!)
  • Capitalized_Words_With_Underscores(丑恶!)

还有一种风格,即便用短的仅有前缀将相关的称号分组在一起。这在Python中并不常见,但出于完好性考虑说到。例如,os.stat() 函数回来一个元组,其项的传统命名为 st_modest_sizest_mtime 等。这样做是为了着重与POSIX体系调用结构的字段的对应关系,这有助于那些熟悉该结构的程序员。

X11库在其一切公共函数前运用前缀 X。在Python中,一般以为这种风格是不必要的,由于特点和办法名都带有目标前缀,而函数名都带有模块名前缀。

此外,还辨认以下运用前导或跟随下划线的特别办法(这些一般可以与任何命名约好结合运用):

  • _single_leading_underscore:弱的“内部运用”指示符。例如,from M import * 不会导入以下划线最初的目标的称号。
  • single_trailing_underscore_:依照惯例用于防止与Python要害字抵触,例如 tkinter.Toplevel(master, class_='ClassName')
  • __double_leading_underscore:在命名类特点时,调用称号润饰(在类 FooBar 中,__boo 变为 _FooBar__boo;见下文)。
  • __double_leading_and_trailing_underscore__:存在于用户可操控的命名空间中的“magic”目标或特点。例如,__init____import____file__。永久不要创造这样的称号;只能依照文档运用它们。

Prescriptive: Naming Conventions|规矩性:命名约好

Names to Avoid|应防止运用的姓名
  • 永久不要将字符 ‘l’(小写字母 “el”)、’O’(大写字母 “oh”)或 ‘I’(大写字母 “eye”)作为单个字符的变量名运用

  • 在某些字体中,这些字符与数字 1 和 0 难以差异。当有运用 ‘l’ 的激动时,请改用 ‘L’。

ASCII Compatibility|ASCII 兼容性

规范库中运用的标识符有必要与 ASCII 兼容,如 PEP 3131 的战略部分中所述。

坚持模块与ASCII兼容。关于任何标识符命名(例如,类名或函数名),只运用ASCII字符。即便某些Unicode字符看起来像ASCII字符,也十分重要坚持运用ASCII以坚持兼容性。

Package and Module Names|包和模块称号

类名一般应运用CapWords约好。

在接口被记载并首要用作可调用目标的状况下,可以运用函数的命名约好。

请留意,内置称号有一个独自的约好:大多数内置称号都是单词(或两个单词连在一起),仅在反常称号和内置常量中运用CapWords约好

Type Variable Names|类型变量称号

在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|反常称号

由于反常应该是类,因而在这儿运用类命名约好。可是,应该在反常称号上运用后缀“Error”(假如反常确实是过错)

class CustomError(Exception):
    pass
class FileReadError(IOError):
    pass
Global Variable Names|全局变量称号

希望这些变量仅在一个模块内部运用。约好与函数的约好简直相同。

规划为经过 from M import * 运用的模块应该运用 __all__ 机制防止导出全局变量,或许运用在这些全局变量前加下划线的旧约好(这或许是为了标明这些全局变量是“模块非揭露的”)。

_global_variable = 42  # 模块非揭露的全局变量
__all__ = ['public_variable']  # 经过 from module import * 导入的揭露变量列表
public_variable = 10  # 揭露的全局变量
Function and Variable Names|函数和变量的命名

函数名应该是小写的,单词之间可以用下划线分隔以进步可读性。

变量名遵从与函数名相同的约好。

mixedCase 仅答应在已经是主流风格的上下文中运用(例如 threading.py),以坚持向后兼容性。

# 引荐
def calculate_total(items):
    # 函数体
    pass
user_name = "John"
total_amount = 100.0
# 不引荐
def calculateTotal(items):
    # 防止运用 mixedCase 风格
    pass
Function and Method Arguments|函数和办法参数

一直将self用作实例办法的榜首个参数。

一直将cls用作类办法的榜首个参数。

假如函数参数的称号与保存要害字抵触,一般最好附加一个单个下划线,而不是运用缩写或拼写损坏。因而,class_clss更好。 (也许更好的办法是经过运用同义词来防止此类抵触。)

class MyClass:
    def __init__(self, x):
        self.x = x
    def instance_method(self):
        print(f"Instance method called. Value of x: {self.x}")
    @classmethod
    def class_method(cls):
        print("Class method called.")
# 创立类的实例
obj = MyClass(42)
# 调用实例办法
obj.instance_method()
# 调用类办法
MyClass.class_method()
Method Names and Instance Variables|办法称号和实例变量

应该运用函数命名规矩,即小写字母,单词之间用下划线分隔以进步可读性

仅在非公共办法和实例变量中运用一个前导下划线。

为了防止与子类抵触,运用两个前导下划线来调用Python的称号混杂规矩。

Python运用类名混杂这些称号:假如类Foo有一个名为__a的特点,就无法经过Foo.__a拜访它(坚持的用户依然可以经过调用Foo._Foo__a来获取拜访权限)。一般,双前导下划线应仅用于防止与规划为被子类化的类中的特点产生称号抵触。

留意:关于运用__names存在一些争议。

class MyClass:
    def __init__(self):
        # 运用一个前导下划线标明这是一个非公共实例变量
        self._non_public_variable = 42
    def public_method(self):
        print("This is a public method.")
    def _non_public_method(self):
        # 运用一个前导下划线标明这是一个非公共办法
        print("This is a non-public method.")
class SubClass(MyClass):
    def __init__(self):
        super().__init__()
        # 运用两个前导下划线调用称号混杂规矩,防止与父类的特点抵触
        self.__subclass_variable = "Subclass variable"
    def __subclass_method(self):
        # 运用两个前导下划线调用称号混杂规矩,防止与父类的办法抵触
        print("This is a subclass method.")
# 创立类的实例
obj = MyClass()
# 拜访公共办法和实例变量
obj.public_method()
print(obj._non_public_variable)
# 创立子类的实例
sub_obj = SubClass()
# 拜访子类的办法和实例变量
sub_obj._SubClass__subclass_method()
print(sub_obj._SubClass__subclass_variable)
Constants|常量

常量一般在模块等级界说,并运用一切大写字母,用下划线分隔单词。示例包括 MAX_OVERFLOWTOTAL

Designing for Inheritance|为承继而规划

总是决议类的办法和实例变量(统称为“特点”)是公共的仍是非公共的。假如有疑虑,挑选非公共;将其揭露比将公共特点变为非公共特点更简略。

公共特点是您希望类的不相关客户运用的特点,您承诺防止向后不兼容的更改。非公共特点不打算由第三方运用;您不保证非公共特点不会更改乃至被删去。

我们在这儿不运用“私有”这个术语,由于在Python中没有真正的私有特点(除非做了一般不必要的作业)。

另一类特点是属于“子类 API”(在其他语言中一般称为“受维护”)的特点。某些类规划为可承继,可以经过承继或修正类的行为来运用这些特点。在规划这样的类时,请慎重明晰地决议哪些特点是公共的,哪些是子类 API 的一部分,哪些真正只能由基类运用。

class Person:
    def __init__(self, name, age):
        self._name = name  # 非公共特点
        self.__age = age   # 子类 API 特点
    def get_name(self):
        return self._name
    def set_name(self, name):
        self._name = name
    def get_age(self):
        return self.__age
    def set_age(self, age):
        if age > 0:
            self.__age = age
# 运用示例
person = Person("Alice", 25)
# 公共办法和非公共特点的拜访
print(person.get_name())  # Alice
person.set_name("Bob")
print(person.get_name())  # Bob
# 子类 API 特点的拜访
print(person.get_age())  # 25
person.set_age(30)
print(person.get_age())  # 30

在这个比如中,_name 被规划为非公共特点,而 __age 被规划为子类 API 特点。运用相应的 gettersetter 办法来拜访和修正这些特点,这样可以供给一定的操控和封装性。请留意,这儿运用的是约好而不是强制性规矩,Python 并不会强制特点的可见性。

在此基础上,以下是Python的原则:

  • 公共特点不应以下划线最初。

    • 假如公共特点称号与保存要害字抵触,请在特点称号后附加一个单下划线。这比运用缩写或拼写过错更可取。(可是,请留意,关于已知是类的变量或参数,特别是类办法的榜首个参数,cls是首选的拼写。)
  • 关于简略的公共数据特点,最好只揭露特点称号,而不是杂乱的拜访器/修正器办法。

    • 请记住,Python为将来的增强供给了一条简略的路径,假如您发现简略的数据特点需求增加功用性行为。在这种状况下,运用特点将功用完成隐藏在简略的数据特点拜访语法之后。
    • 尝试使功用行为无副作用,虽然缓存等副作用一般是可以承受的。
    • 防止运用计算成本昂扬的操作的特点;特点标明调用者信任拜访是(相对)廉价的。
  • 假如您的类旨在被子类化,而且有一些不希望子类运用的特点,请考虑运用双下划线最初和无下划线结尾的称号。

    • 这会调用Python的称号混杂算法,其中类的称号被混杂到特点称号中。这有助于防止在子类中意外包括具有相同称号的特点时产生特点称号抵触。
    • 请留意:
      • 只运用简略类名作为混杂称号,因而假如子类挑选相同的类名和特点名,依然或许产生称号抵触。
      • 称号混杂或许会使某些用处,如调试和__getattr__(),变得不太便利。可是,称号混杂算法有很好的文档记载,可以手动履行。
    • 并非一切人都喜欢称号混杂。请尽力平衡防止意外称号抵触的需求和高档调用者的潜在运用。

Public and Internal Interfaces| 公共和内部接口

向后兼容性保证仅适用于公共接口。因而,用户有必要可以明晰地差异公共接口和内部接口。

  1. 公共接口的明晰界说。

    • 已记载的接口被以为是公共的,除非文档明晰声明它们是临时或内部接口,免除一般的向后兼容性保证。一切未记载的接口都应被视为内部接口。

      def public_function():
          """This is part of the public interface."""
          ...
      
  2. 运用__all__特点明晰声明公共API。

    • 为了更好地支撑内省,模块应该运用__all__特点明晰声明其公共API的称号。将__all__设置为空列表标明该模块没有公共API。

      __all__ = ['public_function', 'public_class']
      
  3. 即便运用__all__,内部接口也应增加前导下划线。

    • 即便运用__all__特点,内部接口(包、模块、类、函数、特点等)仍应以单个前导下划线作为前缀。

      _internal_function = ...
      
  4. 包括命名空间的内部性。

    • 假如包括命名空间(包、模块或类)被视为内部的,则其包括的接口也被视为内部的。
  5. 导入的称号应被视为完成细节。

    • 其他模块不得依靠对导入称号的直接拜访,除非它们是包括模块 API 的明晰文档部分,例如 os.path 或包的 __init__ 模块从子模块中暴露功用。

经过明晰界说公共接口和内部接口,可以保证用户在运用公共功用时有安稳的体会,而内部完成的改变则不会影响用户的代码。这种明晰的接口规划有助于进步代码的可维护性和可用性。

Programming Recommendations|编程主张

  • 代码应该以不影响 Python 的其他完成(PyPy、Jython、IronPython、Cython、Psyco等)的办法编写。

  • 防止依靠于 CPython 特定的优化。

    • 不要依靠于 CPython 关于办法为 a = ba = a b 的原地字符串连接的高效完成。这种优化在 CPython 中也很软弱(仅适用于某些类型),在不运用引用计数的完成中底子不存在。在库的性能灵敏部分,应该运用 ''.join() 办法,以保证在不同的完成中串联产生在线性时间内。
  • 运用 isis not 进行与单例的比较。

    • 比较单例目标(如 None)时,应一直运用 isis not,而不是相等运算符。

      # Good
      if some_variable is None:
          print("It's None")
      # Avoid
      if some_variable == None:
          print("It's None")
      
  • 留意运用 if x 时保证目的。

    • 当测试默以为 None 的变量或参数是否被设置为其他值时,慎重运用 if x,而更应该运用 if x is not None。其他值或许具有在布尔上下文中为假的类型(例如容器)。
  • 运用 is not 操作符而不是 not ... is。虽然两者在功用上相同,但前者更易读,更受欢迎:

    # 正确:
    if foo is not None:
    # 过错:
    if not foo is None:
    
  • 在完成具有丰富比较的排序操作时,最好完成一切六个操作(__eq____ne____lt____le____gt____ge__),而不是依靠其他代码仅履行特定的比较。为了最小化作业量,functools.total_ordering() 装饰器供给了一个东西,用于生成缺失的比较办法。

    • __eq__ (Equal): x == y
    • __ne__ (Not Equal): x != y
    • __lt__ (Less Than): x < y
    • __le__ (Less Than or Equal): x <= y
    • __gt__ (Greater Than): x > y
    • __ge__ (Greater Than or Equal): x >= y

    PEP 207 指出 Python 假定了反射性规矩。因而,解说器或许将 y > xx < y 交换,y >= xx <= y 交换,并或许交换 x == yx != y 的参数。sort()min() 操作保证运用 < 运算符,而 max() 函数运用 > 运算符。

    但最好完成一切六个操作,以防止在其他上下文中引起混杂。

    from functools import total_ordering
    @total_ordering
    class MyClass:
        def __init__(self, value):
            self.value = value
        def __eq__(self, other):
            return self.value == other.value
        def __lt__(self, other):
            return self.value < other.value
    

    经过运用 @total_ordering 装饰器,你只需求界说 __eq____lt__ 办法,而其他的比较办法会被主动生成。这可以减少你完成的代码量,同时保证了正确的比较行为。

  • 一直运用 def 句子,而不是将 lambda 表达式直接绑定到标识符的赋值句子:

    # 正确:
    def f(x): return 2*x
    # 过错:
    f = lambda x: 2*x
    

    榜首种办法意味着生成的函数目标的称号具体为 'f',而不是通用''。这关于回溯和字符串标明更有用。运用赋值句子消除了 lambda 表达式可以相关于显式 def 句子供给的仅有优点(即它可以嵌套在较大表达式中)的优点。

  • 将反常派生自 Exception 而不是 BaseException。直接从 BaseException 承继应该保存给那些简直总是不应该捕获的反常。 规划反常层次结构时,应依据捕获反常的代码或许需求的差异,而不是反常被引发的方位。力求经过程序办法答复“产生了什么问题?”这个问题,而不仅仅是陈说“产生了问题”(参见 PEP 3151,以了解内置反常层次结构的比如,学到了这个经历)。 类命名约好也适用于这儿,虽然假如反常是过错,应该给反常类增加后缀 “Error”。用于非局部流程操控或其他办法的信号传递的非过错反常不需求特别的后缀。

    class CustomError(Exception):
        pass
    class AnotherError(Exception):
        pass
    

    CustomErrorAnotherError都是从Exception派生的,它们标明过错状况。这使得在处理反常时更简略了解反常的类型。

  • 恰当地运用反常链接raise X from Y 应该用于指示明晰的替换,而不会丢失原始的回溯。 当有意替换内部反常(运用 raise X from None)时,请保证将相关细节传递给新的反常(例如,在将 KeyError 转换为 AttributeError 时保存特点称号,或许在新的反常音讯中嵌入原始反常的文本)。

    try:
        # some code that may raise an exception
        result = 10 / 0
    except ZeroDivisionError as original_exception:
        # raise a new exception with additional context
        raise ValueError("Invalid calculation") from original_exception
    

    在这个比如中,ValueError反常代替了ZeroDivisionError反常,并经过from original_exception保存了原始反常的回溯信息。

  • 捕获反常时,尽量提及具体的反常,而不要运用裸的 except: 子句

    try:
        import platform_specific_module
    except ImportError:
        platform_specific_module = None
    

    裸的 except: 子句会捕获 SystemExitKeyboardInterrupt 反常,使得运用 Control-C 更难中止程序,而且或许掩盖其他问题。假如你想捕获一切标明程序过错的反常,运用 except Exception:(裸的 except 等效于 except BaseException:)。

    一个杰出的经历法则是将裸的 except 子句的运用约束为两种状况:

    1. 假如反常处理程序将打印或记载回溯信息;至少用户将意识到产生了过错。
    2. 假如代码需求进行一些整理作业,但然后答应反常上升到上层运用 raise。在这种状况下,try...finally 或许是处理的更好办法。
    # 不好的比如:裸的 except,捕获简直一切反常,包括 SystemExit 和 KeyboardInterrupt
    try:
        # some code that may raise an exception
        result = 10 / 0
    except:
        # handle the exception
        print("An error occurred")
    # 好的比如:捕获指定的反常,或许至少捕获 Exception
    try:
        # some code that may raise an exception
        result = 10 / 0
    except ZeroDivisionError:
        # handle the specific exception
        print("Cannot divide by zero")
    except Exception as e:
        # handle other exceptions
        print(f"An error occurred: {e}")
    
  • 在捕获操作体系过错时,更倾向于运用在 Python 3.3 中引进的显式反常层次结构,而不是查看 errno 值。

  • 此外,关于一切的 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)
    
  • 当一个资源仅在代码的特定部分运用时,应运用 with 句子保证在运用后及时而可靠地进行整理。也可以运用 try/finally 句子。

    # 运用 try/finally 句子办理资源
    resource = acquire_resource()
    try:
        # 在此处运用资源
        process_resource(resource)
    finally:
        # 保证在任何状况下都会开释资源
        release_resource(resource)
    
  • 当上下文办理器履行除获取和开释资源之外的操作时,应经过独自的函数或办法调用它们:

    # Correct:
    with conn.begin_transaction():
        do_stuff_in_transaction(conn)
    # Wrong:
    with conn:
        do_stuff_in_transaction(conn)
    

    后一种示例没有供给任何信息,标明 __enter____exit__ 办法正在履行除在业务后封闭连接之外的其他操作。在这种状况下,明晰是很重要的。

    class DataProcessor:
        def __enter__(self):
            # 在这儿履行获取资源的操作,例如翻开文件
            self.file = open('example.txt', 'r')
            return self
        def process_data(self):
            # 在这儿履行处理数据的操作
            data = self.file.read()
            print(data.upper())  # 举例:将文本转换为大写并打印出来
        def __exit__(self, exc_type, exc_value, traceback):
            # 在这儿履行开释资源的操作,例如封闭文件
            self.file.close()
    # 运用上下文办理器
    with DataProcessor() as dp:
        dp.process_data()
    # 文件已在 with 句子块完毕时主动封闭
    

    在这个比如中,DataProcessor 类是一个上下文办理器,负责处理文件的翻开和封闭,以及数据的处理。__enter__ 办法用于获取资源,__exit__ 办法用于开释资源。process_data 办法用于处理数据。将数据处理的逻辑提取到 process_data 办法中,使得上下文办理器的责任明晰可见。

  • 在 return 句子中坚持共同性。一个函数中的一切 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)
    
  • 运用 ''.startswith() ''.endswith()而不是字符串切片来查看前缀或后缀。 startswith()endswith() 更明晰,更不简略出错:

    # Correct:
    if foo.startswith('bar'):
    # Wrong:
    if foo[:3] == 'bar':
    
  • 目标类型的比较应该一直运用 isinstance() 而不是直接比较类型:

    # Correct:
    if isinstance(obj, int):
    # Wrong:
    if type(obj) is type(1):
    
  • 关于序列(字符串、列表、元组),利用空序列为假的现实:

    # Correct:
    if not seq:
    if seq:
    # Wrong:
    if len(seq):
    if not len(seq):
    
  • 不要编写依靠于明显跟随空白的字符串字面值。这种跟随空白在视觉上是无法差异的,而一些编辑器(或最近的reindent.py)将对它们进行修剪。

    # 不主张的写法(依靠于字符串结尾的空白)
    message = "This is a message with trailing space.    "
    # 引荐的写法(去掉结尾的空白)
    message = "This is a message without trailing space."
    

    假如确实需求保存结尾空白,可以考虑运用特别字符(如空格或制表符)进行标明,以防止在不同环境中的处理不共同。

  • 不要运用 == 将布尔值与 TrueFalse 进行比较:

    # Correct:
    if greeting:
    # Wrong:
    if greeting == True:
    # Wrong:
    if greeting is True:
    
  • try...finally 结构的 finally 块内部运用 return/break/continue 这类操控流句子,假如这些句子会跳出 finally 块,是不鼓舞的。这是由于这样的句子会隐式撤销在 finally 块中传达的任何活动反常:

    # Wrong:
    def foo():
        try:
            1 / 0
        finally:
            return 42
    

    在这个比如中,当除法操作引发 ZeroDivisionError 时,finally 块中的 return 句子会撤销反常的传达,而且函数的回来值将是 42,而不是引发的反常。为了防止这种状况,最好在 finally 块中防止运用可以跳出块的操控流句子,以保证反常可以正确传达。假如需求在 finally 块中履行整理操作,可以考虑将整理逻辑放在 finally 块之外,或许运用其他办法来处理整理逻辑。

Variable Annotations|函数注释

PEP 526 引进了变量注释。对它们的款式主张与上述函数注释的主张相似:

  • 模块级变量、类和实例变量以及局部变量的注释应在冒号后有一个空格。

  • 在冒号之前不应有空格。

  • 假如赋值右侧有内容,则等号两边应该正好有一个空格:

    # 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
    
  • 虽然 PEP 526 被承受用于 Python 3.6,但变量注释语法是一切 Python 版别的存根文件中首选的语法(有关具体信息,请参阅 PEP 484)。

References|参阅