参考文章链接
https://www.python.org/dev/peps/pep-0008/
Python编码规范(Style Guide for Python Code)_L-CSDN博客
重新学习python
代码布局
缩进
每个缩进级别使用 4 个空格。
方式一:
# 与开始分隔符对齐。
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)
错误:
# 不使用垂直对齐时禁止在第一行使用参数。
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 由于缩进无法区分,因此需要进一步缩进。
def long_function_name(
var_one, var_two, var_three,
var_four):
打印(var_one)
if语句
当if语句的条件部分足够长以要求将其写成多行时,值得注意的是,两个字符的关键字(即if)、单个空格和左括号的组合创建了一个自然的多行条件的后续行的 4 个空格缩进。这可能会与嵌套在if语句中的缩进代码套件产生视觉冲突,该代码也自然会缩进 4 个空格。
# 没有额外的缩进。
if (this_is_one_thing and
that_is_another_thing):
do_something()
# 添加注释,这将在编辑器中提供一些区别
# 支持语法突出显示。
if (this_is_one_thing and
that_is_another_thing):
# Since both conditions are true, we can frobnicate.
do_something()
# 在条件续行上添加一些额外的缩进。
if (this_is_one_thing
and that_is_another_thing):
do_something()
if 语句的缩进不限于以上内容。
括号(大括号、方括号、圆括号)
多行结构上的右大括号/方括号/圆括号可以排列在列表最后一行的第一个非空白字符下,如下所示:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
或者它可以排列在开始多行结构的行的第一个字符下,如下所示:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
注:
空格是首选的缩进方法。
制表符应仅用于与已使用制表符缩进的代码保持一致。
Python 不允许混合使用制表符和空格进行缩进。
最大行宽
每行长度限制为 72 个字符。可以使用反斜杠进行延续。
应该在二次运算符之前还是之后换行?
前后都可以,推荐在后。
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
空行
用两个空行包围顶级函数和类定义。
类中的方法定义被一个空行包围。
可以(谨慎地)使用额外的空行来分隔相关功能组。一堆相关的单行代码之间可以省略空行(例如一组虚拟实现)。
在函数中谨慎使用空行来指示逻辑部分。
Python 接受 control-L(即 ^L)换页符作为空格;
源文件编码
核心 Python 发行版中的代码应始终使用 UTF-8,并且不应有编码声明。
Imports
导入通常应该在不同的行上,例如:
# 正确:
import os
import sys
from elasticsearch import Elasticsearch
不推荐使用以下方式:
# 错误:
import os
import sys
from elasticsearch import Elasticsearch
不过可以:
#正确
from common import text_similarity, getNextValue
imports总是放在文件的顶部,就在任何模块注释和文档字符串之后,以及模块全局变量和常量之前。
imports应按以下顺序分组:
- 标准库导入。
- 相关的第三方进口。
- 本地应用程序/库特定导入。
应该在每组导入之间放置一个空行。
模块级“Dunders”名称
“Dunders”名称:带有两个前导下划线和两个后置下划线的名称,例如: __all__, __author__, __version__等等。应当放在模块文档(module docstring)之后,所有import语句之前(from __future__ imports除外,from __future__ imports放在模块文档之后,所有import语句之前),例如:
"""This is the example module.
This module does stuff.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys
字符串引用(String Quotes)
在Python中,单引号和双引号是一样的。本PEP不推荐这样,而是选择其中一条并坚持使用。当字符串中包含单引号和双引号时,使用另外一个避免反斜杠的转义。
表达式和语句中的空格
圆括号,中括号,大括号内部没有空格,如下:
推荐:
spam(ham[1], {eggs: 2})
不推荐:
spam( ham[ 1 ], { eggs: 2 } )
逗号和小括号之间没有空格,如下:
推荐:
foo = (0,)
不推荐:
bar = (0, )
逗号,分号,冒号之前没有空格,如下:
推荐:
if x == 4: print x, y; x, y = y, x
不推荐:
if x == 4 : print x , y ; x , y = y , x
不用为了赋值符号对齐而使用多个空格,如下:
推荐:
x = 1
y = 2
long_variable = 3
不推荐:
x = 1
y = 2
long_variable = 3
注释(Comments)
与代码冲突的注释比没有注释更糟糕。当代码发生变化时,始终优先保持注释的更新。注释应该是完整的句子,第一个单词应该大写,除非它是一个以小写字母开头的标识符(永远不要改变标识符的大小写!)。来自非英语国家的Python程序员:请用英语写您的注释,除非您有120%的信心这些代码永远不会被不使用您的语言的人阅读。
块注释(Block Comments)
块注释一般使用在几行代码之前,与代码缩进相同,每行使用#开始,注释内容和#之间有一个空格,例如:
# The SAG solver releases the GIL so it's more efficient to use
# threads for this solver.
if self.solver in ['sag', 'saga']:
backend = 'threading'
else:
backend = 'multiprocessing'
如果注释分多个段落,段落之间使用单个#分隔,例如:
# The SAG solver releases the GIL so it's more efficient to use
#
# threads for this solver.
if self.solver in ['sag', 'saga']:
backend = 'threading'
else:
backend = 'multiprocessing'
行内注释(Inline Comments)
内联注释是与语句在同一行上的注释。尽量少用行内注释。语句与行内注释之间至少两个空格或更多,#和注释内容之间一个空格,如下:
x = x + 1 # Compensate for border
文档字符串(Documentation Strings)
Documentation Strings也称为docstrings。为所有公共模块、函数、类和方法编写文档字符串。对于非公共方法,docstring不是必需的,但是应该有一个描述该方法功能的注释。这个注释应该出现在def行之后。描述良好的文档字符串约定:结束多行docstring的三个双引号"""应该单独在一行上,例如:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
对于单行docstring,三个双引号"""应该在与文档字符串在同一行上,例如:
def kos_root():
"""Return the pathname of the KOS root directory."""
global _kos_root
if _kos_root: return _kos_root
...
命名约定(Naming Conventions)
Python库的命名约定有点混乱,所以我们永远不会得到完全一致的结果——尽管如此,下面是目前推荐的命名标准。应该按照这些标准编写新的模块和包(包括第三方框架),但是如果现有库具有不同的风格,则最好采用内部一致性。
几种命名风格:
单个小写字符:b
单个大写字符:B
小写单词:age
大写单词:NAME
下划线连接小写单词:lower_case_with_underscores
下划线连接大写单词:UPPER_CASE_WITH_UNDERSCORES
驼峰命名(每个单词首字母大写):CapitalizedWords
每个单词首字母大写(第一个单词首字母小写):mixedCase
另外,使用前导或后置下划线的特殊格式:
(1)_single_leading_underscore:前面添加单个下划线表示内部使用,例如:import语句from M import *不会导入单个下划线开始的对象。
(2)single_trailing_underscore_:后面添加单个下划线避免与关键字冲突,例如:
Tkinter.Toplevel(master, class_='ClassName')
(3)__double_leading_underscore:命名类属性时使用双下划线开头。
(4)__double_leading_and_trailing_underscore__:前后使用双下划线,用于命名空间中的魔法(“magic”)对象和属性。例如:__init__, __import__ or __file__,永远不要发明这样的名字;只在文档中使用它们。
不要使用“l”,“O”,“i”等作为单个字符变量的名字,因为有时它们无法与数字“1”和“0”区分。
包和模块名
模块名字全部小写,可以使用下划线连接。
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).
类名称(Class Names)
类名使用驼峰命名法。
类型变量名称(Type Variable Names)
PEP 484中引入的类型变量的名称通常应该使用驼峰命名法,它们更喜欢短名称: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”后缀。
全局变量名称(Global Variable Names)
我们希望这些变量只在一个模块中使用。
函数和变量名称(Function and Variable Names)
函数名和变量名使用小写字母,单词之间使用下划线。变量命名和函数相同。mixedCase只允许在已经是主流样式的上下文中使用(例如thread .py),以保持向后兼容性。
函数和方法参数(Function and Method Arguments)
(1)实例方法:始终使用self作为第一个参数;
(2)类方法:始终使用cls作为第一个参数;
如果函数参数的名称与保留关键字冲突,通常最好附加一个尾随下划线,而不是使用缩写或拼写错误。因此class_比clss好。(或许更好的办法是使用同义词来避免这种冲突。)
方法名称和实例变量(Method Names and Instance Variables)
(1)和函数名称命名规定相同
(2)仅对非公共方法和实例变量使用一个前导下划线
常量(Constants)
常量通常在模块级别上定义,并使用大写字母和下划线分隔单词。例如MAX_OVERFLOW和TOTAL。
继承的设计(Designing for Inheritance)
总是决定类的方法和实例变量(统称:“属性”)是公共的还是非公共的。如有疑问,选择非公开;稍后将其公开比将公共属性设置为非公共更容易。我们在这里不使用术语“私有”,因为在Python中没有真正私有的属性。
(1)公共属性应该没有前导下划线
(2)如果公共属性名与保留关键字冲突,请在属性名后面追加一个下划线
(3)如果类打算被子类化,并且不希望子类使用的属性,那么可以考虑使用双前导下划线和无后置下划线来命名它们。
公共接口和内部接口(Public and Internal Interfaces)
(1)为了更好地支持自省,模块应该使用__all__属性显式地在其公共API中声明名称。将__all__设置为空列表表明模块没有公共API。
设计推荐(Programming Recommendations)
(1)代码的编写方式应该不影响Python的其他实现(PyPy、Jython、IronPython、Cython、Psyco等)。例如,不依赖CPython的高效实现就地字符串连接的语句形式+ = b或a = a + b。这种优化是脆弱的甚至在CPython的(只适用于某些类型)和不存在在不使用refcounting实现。在库的性能敏感部分,应该使用“.join()表单”。这将确保在不同实现之间以线性时间进行连接。
(2)使用 is not 而不是not…is。虽然这两个表达式在功能上是相同的,但前者更易于阅读和首选。
(3)与None之类的单例进行比较时,应该始终使用is或is not而不是相等运算符。
(4)在实现具有丰富比较的排序操作时,最好实现所有6个操作(__eq__、__ne__、__lt__、__le__、__gt__、__ge__),而不是依赖其他代码只执行特定的比较。
(5)始终使用def语句,而不是直接将lambda表达式绑定到标识符的赋值语句。
推荐:
def f(x): return 2*x
不推荐:
f = lambda x: 2*x
(6)捕获异常时,尽可能地提到特定的异常,而不是使用空的except:子句
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
(7)不要使用==将布尔值与True或False进行比较。
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
(8)对于序列(字符串、列表、元组),使用空序列为假的事实
Yes: if not seq:
if seq:
No: if len(seq):
if not len(seq):
(9)对象类型比较应该始终使用isinstance(),而不是直接比较类型
Yes: if isinstance(obj, int):
No: if type(obj) is type(1):