NOTE(注意): 随着时间的推移,更好的编程方式可能会陆续出现,以下基于PEP8整理总结于2023-12-18.
 由于加入了自己的一些见解,所以本文并不是PEP8的翻译版本,所以跟PEP8并不100%相同。其中样例代码只摘取了经典的常见的一部分。
 以下部分内容仅代表个人观点,请理性对待,如有错误的地方欢迎指出。
 希望本文能帮助初学python的同学。
 为了方便解答一些问题,热爱python的以及正在学习python的小伙伴可以来这里一起交流学习,Q企鹅裙826238287
1、缩进
缩进使用四个空格缩进(可设置Tab键为四个空格)
 单行太多时需要换行,应该优先使用Python隐式的换行方式,即利用圆括号、方括号和大括号内的行连接垂直对齐,或者使用悬挂缩进(悬挂缩进个人感觉不够美观)。
# 推荐的示范:# 函数
# 额外添加4个空格(额外的缩进级别)以区分参数和其他参数
# 即缩进两个级别,首行无参数
def long_function_name(var_one, var_two, var_three,var_four):print(var_one)# 多行结构
# 多行结构中的右大括号/大括号/圆括号可以排在列表最后一行的第一个非空白字符下面
# 或它可以排在开始多行结构的行的第一个字符下面
my_list = [1, 2, 3,4, 5, 6,
]
result = some_function_that_takes_arguments('a', 'b', 'c','d', 'e', 'f',
)
2、制表符(Tab)和空格
空格是首选的缩进方法。
 Python 3 不允许混合使用制表符和空格进行缩进。
 当历史代码使用Tab缩进时请跟历史代码保持一致,否则请使用4空格进行缩进。
 几乎99%的代码都是使用4空格缩进(没有实际的调研,资深程序员的经验)
3、最大行长度
单行字符数量最大79个字符,许多IDE都支持设置最大字符长度
 建议在开始一个新项目时,提前设置好,便于阅读。
 当然许多已有的历史项目可能有自己的约定,比如120,如果有,请与历史项目的CodeFormat保持一致。不然可能会让项目代码看起来丑陋无比(当然它并不影响运行)。
4、运算符前后断线
对于过长的运算表达式,需要在运算符位置换行,具体是在运算符前换行还是运算符后换行,这个颇有争议。
 从几十年经验的老程序员建议来看,是在运算符后面换行,即如下:
#运算符后换行
income = (gross_wages +taxable_interest +(dividends - qualified_dividends) -ira_deduction -student_loan_interest)
但是数学家Donald Knuth在计算机和排字领域中分析了很多,结论就是操作符前换行更易读,如下:
# 运算符前换行
income = (gross_wages+ taxable_interest+ (dividends - qualified_dividends)- ira_deduction- student_loan_interest)
这里建议根历史项目保持一致,如果是新项目,个人建议运算符前换行,更易读。
5、空白行
1、顶层函数和类定义之间应该有两个空行
 2、类内方法的定义间隔一个空行
 3、功能类别分组可使用两个空行进行简单分组(易读)
 Python接受control-L(即^L)格式换行字符作为空白符;许多工具将这些字符视为页面分隔符,因此您可以使用它们来分隔文件中相关部分的页面。(符合标准但不推荐,兼容性不好)
def top_function():passclass MyClass(object):  # 与上方顶层函数空两行def __init__(self):passdef func_1(self):passdef func_2(self):  # 与上方func_1类方法空一行pass
6、源文件编码
核心Python发行版中的代码应该始终使用UTF-8,并且不应该有编码声明。
 在标准库中,非utf-8编码应该仅用于测试目的。
 尽量避免使用非ascii字符,最好仅用于表示地点和人名。
 如果使用非ascii字符作为数据,请避免使用嘈杂的Unicode字符。
 Python标准库中的所有标识符必须使用纯ascii标识符,
 并且应该尽可能使用英语单词(在许多情况下,使用非英语的缩写和技术术语)。
 使用英文通常便于国际化,当然在某些特殊情况下可以使用其他的,比如中文拼音(中国文化博大精深,非专有名词应尽量避免使用拼音,容易存在歧义,比如shijie,你很难知道我要表达的是“石阶”还是“世界”)
7、Imports包导入
1、导入通常要在单独行
 2、导入应始终放在文件顶部
 3、导入应该按如下顺序分组
 (1)、标准库导入
 (2)、相关的第三方库导入
 (3)、本地应用程序/库的导入
 4、每组导入应用一个空白行进行分隔
 5、优先使用绝对导入,而不是相对(易读性好,错误提示更友好,不容易出现循环引用)
 6、避免通配符全量(from mypkg import *)导入
# 推荐示范
import os
import sysfrom subprocess import Popen, PIPEimport mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
8、模块级的DunderNames(双下划线开头结尾的变量名)
如__all__, __author__, __version__等,应放在模块文档字符串(docstrings)之后,但要在除__future__ import之外的任何导入语句之前。
 future import比较特殊,Python强制要求future-imports必须出现在模块中除docstrings之外的任何其他代码之前
"""This is the example module.
This is docstrings.
This module does stuff.
"""from __future__ import barry_as_FLUFL  # docstring后面,其他的import和DunderNames前面__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'  # 除__future__ import之外的任何import语句之前import os
import sys
9、字符引号
在Python中,单引号字符串和双引号字符串是相同的。PEP没有对此提出建议。
 可以选择一种方式并一直使用下去。
 但是,当字符串包含单引号或双引号字符时,请使用另一个字符以避免字符串中出现反斜杠。它提高了可读性。
 (个人推荐字符串优先使用单引号,因为相比于其他语言需要使用双引号来表示字符串来说,它比较Pythonic)
 Pythonic不太好解释它的意思,总之就是比较有python的个性和特点的意思,简单来说就是python代码更优雅!
10、表达式和语句中的空格
避免出现杂乱的空格
# 推荐示范:
spam(ham[1], {eggs: 2})
foo = (0,)
if x == 4: print(x, y); x, y = y, x# 不推荐的写法
spam( ham[ 1 ], { eggs: 2 } )
bar = (0, )
if x == 4 : print(x , y) ; x , y = y , x
空格的使用比较复杂和繁琐,这里只能列举出常见的,通常在编程的时候IDE会给我们辅助提示,并不需要记忆太多东西。
 其他一些建议:
 避免在任何地方留下空格。因为它通常是不可见的,它可能会令人困惑:例如,反斜杠后面跟着空格和换行符不算作行继续标记。
 总是在这些二元操作符的两边分别用一个空格括起来:赋值(=)、增量赋值(+=、-=等)、比较(==、<、>、!=、<>、<=、>=、in、not in、is、is not)、布尔值(and、or、not)。
 如果使用具有不同优先级的操作符,请考虑在具有最低优先级的操作符周围添加空白。用你自己的判断;但是,永远不要使用多个空格,并且在二进制操作符的两边总是有相同数量的空白。
11、尾部逗号的使用
尾部的逗号通常是可选的,但当形成一个元组时必须强制使用逗号,为了清楚起见,建议将括号明显的写出来(而不是隐式的生成)。
# 推荐示范,显示指明括号
FILES = ('setup.cfg',)# 不推荐示范,隐式指明括号,容易错误,排查问题难以排查
FILES = 'setup.cfg',
多余的尾部逗号是有用的情况,当使用版本控制系统时,当期望值、参数或导入项的列表随着时间的推移而扩展时,它们通常是有用的。
 该模式是将每个值(等)单独放在一行上,总是在后面添加逗号,并在下一行添加右括号/大括号/大括号。
 但是,在结束分隔符的同一行上有一个尾随逗号是没有意义的(除了单例元组)
# 推荐示范:
FILES = ['setup.cfg','tox.ini',]
initialize(FILES,error=True,)# 不推荐示范:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
12、注释
重要!重要!重要!
 与代码功能不符的的注释比没有注释更糟糕。当代码发生变化时,总是优先注意保持注释最新!
 (当一长段代码的返回值应该是True的时候,你却在注释上标记的是False,如果被其他程序员看到了,这个时候我建议你去多穿几层厚的衣服,然后带个安全系数高的头盔,比你继续写代码来的更靠谱)
程序员的苦衷:不想看没有注释的代码,不想写有注释的代码。
 养成良好的习惯,给你的代码加上注释吧。程序员何必为难程序员。
评论的规范:
 1、注释应该是完整的句子。第一个单词应该大写,除非它是以小写字母开头的标识符(永远不要改变标识符的大小写!)
 2、块注释通常由一个或多个由完整句子组成的段落组成,每个句子以句号结尾。
 3、在多句注释中,除了最后一句之外,你应该在句子结束后使用一到两个空格。
 4、确保注释足够的清晰。
 5、来自非英语国家的Python程序员:请用英语写你的注释,除非你120%确定代码永远不会被不讲你的语言的人阅读。
 (个人的一些建议,绝大多数代码都是闭源的,如果团队中不是来自各个国家的成员,注释建议使用母语,他能更好的和更清楚的表达意思,使用它国语言并不能彰显你有多么的NB,反而它有时候更容易<Gu_fcsdn>让队友误解,这是不利的。当然一些对其他字符或语言兼容不好的系统要特殊对待,不过除了专有领域和古董设备以外,这种情况几乎不存在了。)
块注释:
 块注释通常适用于跟踪它们的一些(或所有)代码,并被缩进与代码相同的级别。每一行的block注释从#和一个空格开始(除非它是在注释中输入的文本)。
 块注释中的段落由包含单个#的行分隔。
内联注释:
 内联注释是与语句在同一行的注释。内联注释与语句之间应该至少间隔两个空格。它们应该以#和一个空格开头。
 内联注释是不必要的,如果它们陈述了显而易见的事情,实际上会分散注意力。
 在某些情况下是必要的,如下:
# 无必要的
x = x + 1                 # 对x进行加一# 有必要的
x = x + 1                 # x加一进行补偿逻辑边界
文档注释:
 通常使用三引号(单引号/双引号)进行文档注释
 为所有公共模块、函数、类和方法编写文档字符串。文档字符串对于非公共方法不是必需的,但是您应该有一个注释来描述该方法的功能。这个注释应该出现在定义符之后。
 1、对于多行文档注释来说,头部三引号通常为总结或返回值,结尾三引号请保持在独立行
 2、对于单行文档注释来说,三引号不应该在独立行,而应该在一行
# 多行文档注释
"""Return a foobangOptional plotz says to frobnicate the bizbaz first.
"""# 单行文档注释
"""Return an ex-parrot."""
13、命名约定
Python库的命名约定有点乱,所以我们永远不会完全一致——尽管如此,这里是目前推荐的命名标准。
 新的模块和包(包括第三方框架)应该按照这些标准编写,但是如果现有的库具有不同的风格,则优先考虑内部一致性。
重要部分:
 作为API的公共部分对用户可见的名称应该遵循反映用法而不是实现的约定。
命名风格:
- b(单个小写字母)
- B(单个大写字母)
- lowercase(单个小写单词)
- lower_case_with_underscores(多个单词,下划线表示)
- UPPERCASE(单个大写单词)
- UPPER_CASE_WITH_UNDERSCORES(单个大写单词下划线表示)
- CapitalizedWords(驼峰命名,通常用于类名)
- 在CapWords中使用首字母缩写时,首字母缩写的所有字母都要大写。因此,HTTPServerError比HttpServerError更好
- mixedCase(不同于大写单词的首字母小写字符,小驼峰)
- Capitalized_Words_With_Underscores(这是不推荐的写法!)
此外,可以识别以下使用下划线开头或结尾的特殊形式(这些通常可以与任何大小写约定结合使用):
- _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__: 双下划线开头和结尾的变量,存在于用户控制的命名空间中的“魔法”对象或属性。例如- __init__,- __import__或- __file__。永远不要编造这样的名字,只按照文档的要求使用它们。
命名规则:
 1、避免使用的命名
 不要使用字符’ l '(小写字母el), ’ O ‘(大写字母oh)或’ I '(大写字母eye)作为单字符变量名。
 在某些字体中,这些字符与数字1和0无法区分。当你想用“l”的时候,就用“L”代替。
 2、保持ASCII码兼容
 标准库中使用的标识符必须与ASCII兼容。
 3、包名和模块名
 模块应该有简短的、全小写的名称。如果可以提高可读性,可以在模块名中使用下划线。Python包也应该有简短的、全小写的名称,尽管不鼓励使用下划线。
 当用C或C++编写的扩展模块附带提供更高级别(例如更面向对象)接口的Python模块时,c/c++模块有一个前导下划线(例如_socket)。
 4、类名
 类名通常应该使用CapWords约定。(大驼峰)
 函数的命名约定可以在接口被记录并主要作为可调用对象使用的情况下使用。
 请注意,内置名称的约定是单独的:大多数内置名称都是单个单词(或两个单词一起运行),使用的CapWords约定只用于异常名称和内置常量。
 5、类型变量名
 PEP 484中引入的类型变量的名称通常应该使用CapWords,更倾向于使用短名称:T, AnyStr, Num。建议在用于声明协变或逆变行为的变量后添加后缀_co或_contra:
from typing import TypeVarVT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
6、异常命名
 因为异常应该是类,所以这里适用类命名约定。但是,您应该在异常名称上使用后缀“Error”,如CustomValueError(如果异常实际上是错误)。
 7、全局变量命名
 (我们希望这些变量只能在一个模块中使用。)这些约定与函数的约定大致相同。
 from M import * 应该使用__all__机制来防止输出globals,或者使用更旧的前缀,用下划线来前缀(你可能想要做的),以指示这些全局函数是“非开放模块”。
 8、函数和变量命名
 函数名应该是小写的,必要时用下划线分隔,以提高可读性。
 变量名遵循与函数名相同的约定。
 mixedCase风格只允许在已经是流行风格的上下文中使用(例如threading.py),以保持向后兼容性。
 9、函数和方法参数
 总是使用self作为实例方法的第一个参数。
 总是将cls作为类方法的第一个参数。
 如果函数参数的名称与保留关键字冲突,通常最好在后面附加一个下划线,而不是使用缩写或拼写错误。因此class_比clss好。(也许最好是使用同义词来避免这种冲突。)
 10、方法名和实例变量
 使用函数命名规则:小写字母,必要时用下划线分隔,以提高可读性。
 只对非公共方法和实例变量使用一个前导下划线。
 为了避免与子类的名称冲突,请使用两个前导下划线来调用Python的名称混淆规则。
 Python用类名混淆了这些名称:如果类Foo有一个名为__a的属性,它不能被Foo.__a访问。(如果用户想,用户仍然可以通过调用Foo._Foo__a来获得访问权。)通常,双前导下划线应该仅用于避免与设计为子类化的类中的属性发生名称冲突。
 注意:关于__names的使用存在一些争议。
 11、常量
 常量通常在一个模块级别上定义,并用所有大写字母写在分隔字上。示例包括MAX_OVERFLOW溢出和TOTAL。
 12、继承的设计
 始终决定一个类的方法和实例变量(统称为“属性”)应该是公共的还是非公共的。如果有疑问,选择非公开的;稍后将其设置为公共属性比将公共属性设置为非公共属性更容易。
 公共属性是那些期望与您的类不相关的客户使用的,以避免向后不兼容的更改。非公开(non-public)属性是那些不打算被第三方使用的属性;你不能保证“属性”不会改变或被删除。
 我们在这里没有使用术语“私有”,因为在Python中没有属性是真正私有的。
 另一类属性是“子类API”的一部分(在其他语言中通常称为“protected”)。有些类被设计为可以继承,以扩展或修改类行为的某些方面。在设计这样的类时,要注意明确地决定哪些属性是公共的,哪些属性是子类API的一部分,哪些属性只能由基类使用。
 考虑到这一点,以下是python指南:
- 公共属性不应该有前导下划线。
- 如果公共属性名与保留关键字冲突,请在属性名后面添加一个下划线。这比缩写或错误的拼写更可取。(然而,尽管有此规则,cls是已知为类的任何变量或参数的首选拼写,特别是类方法的第一个参数。)
 注:请参阅上面关于类方法的参数名称推荐。
- 对于简单的公共数据属性,最好只公开属性名称,不使用复杂的accessor/mutator方法。请记住,如果您发现一个简单的数据属性需要发展函数行为,那么Python为将来的增强提供了一条简单的途径。在这种情况下,使用属性将功能实现隐藏在简单的数据属性访问语法之后.
 注1:尽量避免函数行为的副作用,尽管诸如缓存之类的副作用通常是好的
 注2:避免使用属性来计算昂贵的操作;属性符号使调用者相信访问(相对)便捷。
- 如果您的类打算被子类化,并且您有不希望子类使用的属性,请考虑使用双下划线前导而不带下划线来命名它们。这调用了Python的名称混淆算法,其中类的名称被混淆为属性名称。如果子类无意中包含具有相同名称的属性,这有助于避免属性名称冲突。
 注1:注意,在修改后的名称中只使用了简单的类名,因此,如果子类选择了相同的类名和属性名,仍然可能出现名称冲突。
 注2:名称混淆会使某些用途(如调试和__getattr__())变得不那么方便。然而,名称混淆算法有很好的文档记录,并且易于手动执行。
 注3:不是每个人都喜欢人的名字。试着平衡需要避免意外名称与潜在使用的高级调用者的冲突。
13、公共和内部接口
 任何向后兼容性保证只适用于公共接口。因此,重要的是用户能够清楚地区分公共接口和内部接口。
 文档化的接口被认为是公共的,除非文档显式地声明它们是临时的或免除通常的向后兼容性保证的内部接口。所有未归档的接口都应该假定是内部的。
 为了更好地支持自省,模块应该使用__all__属性在其公共API中显式声明名称。将__all__设置为空列表表明该模块没有公共API。
 即使正确设置了__all__,内部接口(包、模块、类、函数、属性或其他名称)仍应以单个下划线作为前缀。
 如果任何包含名称空间(包、模块或类)被认为是内部的,那么接口也被认为是内部的。
 导入的名称应始终被视为实现细节。其他模块不能依赖于对这些导入名称的间接访问,除非它们是包含模块API如os.path的显式文档部分。路径或包的__init__模块,该模块公开子模块的功能。
14、编程建议
- 代码应该以一种不适合其他Python实现的方式编写(PyPy、Jython、IronPython、Cython、Psyco等)。
 例如,不要依赖CPython有效地实现表单a + = b或a = a + b的语句的内串连接。
 在库的性能敏感部分,应使用''. join()这将确保跨各种实现的连接在线性时间内发生。
- 与None之类的单例比较应该总是用is或is not来完成,永远不要等号运算符。
- 另外,当你真正的意思是if x is not None时,要注意不要写if x,例如,在测试默认为None的变量或参数是否被设置为其他值时。另一个值的类型(例如容器)在布尔上下文中可能为false!
- 用is not运算符而不是not ... is多少。虽然这两个表达式在功能上是相同的,但前者更具可读性和首选。
# 推荐示范:
if foo is not None:# 不推荐示范:
if not foo is None:
- 在实现具有丰富比较的排序操作时,最好实现所有6个操作(__eq__,__ne__,__lt__,__le__,__gt__,__ge__),而不是依赖其他代码,只进行一个特别的比较。
- 为了尽量减少工作量,functools.total_ordering()装饰器提供了一个工具来生成缺失的比较方法。
- 始终使用def语句,而不是将lambda表达式直接绑定到标识符的赋值语句。
# 推荐的示范:
def f(x): return 2*x# 不推荐的示范:
f = lambda x: 2*x
第一种形式意味着结果函数对象的名称特别为f而不是通用的<lambda>。一般来说,这对于回溯和字符串表示更有用。赋值语句的使用消除了lambda表达式相对于显式def语句所能提供的唯一好处(即它可以嵌入到更大的表达式中)。
- 从Exception而不是BaseException派生异常。从BaseException直接继承是为那些捕获它们几乎总是错误的异常保留的。
 基于捕获异常的代码可能需要的区别来设计异常层次结构,而不是基于引发异常的位置。目的是回答这个问题“哪里出了问题?”,而不是仅仅指出“发生了问题”
 这里适用于类命名约定,但如果异常是错误,则应该在异常类后面加上后缀“Error”。用于非本地流控制或其他形式的信令的非错误异常不需要特殊后缀。
- 适当地使用异常链。应该使用raise X from Y来指示显式替换,而不会丢失原始的回溯。
 当故意替换内部异常时(使用raise X from None),确保相关细节被转移到新异常(例如在将KeyError转换为AttributeError时保留属性名称,或者在新异常消息中嵌入原始异常的文本)。
- 在捕捉异常时,尽可能指定特定的异常,而不是使用except
# 指定特定异常ImportError
try:import platform_specific_module
except ImportError:platform_specific_module = None
除非 except 将捕获SystemExit和KeyboardInterrupt异常,使中断程序与Control-C更加困难,并可以掩盖其他问题。如果您想要捕捉到信号程序错误的所有异常,则使用except Exception:(等价于except BaseException:)。
 一个好的经验法则是将“except”从句的使用限制在两种情况下:
 1、如果异常处理程序将打印或日志记录示踪器,至少用户将意识到发生了错误。
 2、如果代码需要做一些清理工作,然后让异常通过raise向上传播,try...finally将是一个更好的方法来处理这种情况。
- 在捕获操作系统错误时,请选择Python 3.3中引入的显式异常层次结构,而不是过度认定errno值。
- 此外,对于所有try/except子句,将try子句限制为所需的绝对最小代码量。同样,这避免了掩盖bug
# 推荐示范:
try:value = collection[key]
except KeyError:return key_not_found(key)
else:return handle_value(value)  # 不推荐示范:
try:# 范围太广return handle_value(collection[key])
except KeyError:# 这还将捕获由handle_value()引发的KeyErrorreturn key_not_found(key)
- 当资源是特定代码段的局部资源时,使用with语句确保在使用后及时可靠地清理它。try/finally语句也是可以接受的。
- 只要它们做的不是获取和释放资源,上下文管理器应该通过单独的函数或方法调用
# 推荐示例:
with conn.begin_transaction():do_stuff_in_transaction(conn)# 不推荐示例:
with conn:do_stuff_in_transaction(conn)
后一个例子没有提供任何信息来表明__enter__和__exit__方法除了在事务结束后关闭连接之外正在做其他事情。在这种情况下,明确是很重要的。
- 在返回语句中保持一致。函数中的所有返回语句都应该返回表达式,或者它们都不应该返回表达式。如果任何return语句返回一个表达式,任何没有返回值的return语句都应该显式地将其声明为return None,并且应该在函数末尾显示一个显式的return语句(如果可达的话)
# 推荐示例:
def foo(x):if x >= 0:return math.sqrt(x)else:return Nonedef bar(x):if x < 0:return Nonereturn math.sqrt(x)# 不推荐示例:
def foo(x):if x >= 0:return math.sqrt(x)def bar(x):if x < 0:returnreturn math.sqrt(x)
- 使用''.startswith()和''.endswith()代替字符串切片来检查前缀或后缀。
 startswith()和endswith()更简洁,更不容易出错
# 推荐示例:
if foo.startswith('bar'):# 不推荐示例:
if foo[:3] == 'bar':
- 对象类型比较应该总是使用isinstance(),而不是直接比较类型
# 推荐示例:
if isinstance(obj, int):# 不推荐示例:
if type(obj) is type(1):
- 对于序列(字符串、列表、元组),使用空序列为假的判断方式
# 推荐示例:
if not seq:
if seq:# 不推荐示例:
if len(seq):
if not len(seq):
- 不要编写依赖于重要末尾空白的字符串文字。这样的尾随空格在视觉上是无法区分的,一些编辑器(或者最近的reindent.py)会去除它们。
- 不要使用==将布尔值与True或False进行比较
# 推荐示例:
if greeting:# 不推荐示例:
if greeting == True:# 更糟糕的示例
if greeting is True:
- 使用流控制语句return/break/continue在try...finally结构的finally中,不鼓励流控制语句跳转到finally结构之外,因为这样的语句将隐式取消任何通过finally套件传递的异常
# 不推荐的示例:
def foo():try:1 / 0finally:return 42
15、变量注释
1、模块级变量、类和实例变量以及局部变量的注释应该在冒号后面有一个空格
 2、冒号前不应有空格
 3、如果赋值项有右手边,那么等式两边应该正好有一个空格
# 推荐示例:
code: intclass Point:coords: Tuple[int, int]label: str = '<unknown>'# 不推荐示例:
code:int  # 冒号后没有空格
code : int  # 冒号前的空格class Test:result: int=0  # 等号周围没有空格
PS:尽管Python 3.6接受PEP 526,但变量注释语法是所有Python版本上存根文件的首选语法(详细信息请参阅PEP 484)。
15、最后
以上内容的整理和总结均基于 PEP-8 规范,并增加了自己的一些见解编写。代码风格从来都是一个行为习惯,而不是强制性的规范,所以一些不推荐的示例依然可以正常运行,只是为了更好的便于理解和防止一些奇怪的错误出现不宜排查,而总结的一套比较好的编程习惯。它不能衡量你技术的高低,但是可以让大家都保持一个好习惯。