Python编写规范PEP8
Python是一门很自由的语言。很多场景下都没有很严格的限制,只有一些推荐的规范。但也正因为如此,我们更应该遵循标准规范,这样才能写出良好的代码。其中,在编码风格方面,有一个专门的PEP(Python Enhancement Proposal,Python增强提案)是针对代码风格的指南。我们在编写代码的时候要尽量遵循这个规范。
PEP8 规范
空格与缩进的使用
- 用空格来表示缩进,而不要用制表符(Tab)。最好是4个空格。注意:空格和Tab不能混用,否则会报错。当然你可能会说,我就是混用的,为什么没出过错。这是因为IDE会自动帮你把Tab转成4个空格。
- 和语法相关的缩进都用四个空格表示。(下文将四个空格写为一级缩进)
- 每行的字符数不超过120个字符。太长的行需要进行换行,换行后的新代码在原缩进的基础上再增加一级缩进。
- 函数和类的定义之间,代码前后用两行空行分隔。
- 同一个类中,各个方法之间用一行空行分隔。
- 二元运算符(如+、-、*、/、=)左右两边各保留一个空格。
- 文件的结尾留一行空行。
- 注释中#的后面应该空一格。如果注释前有代码,#前应至少空两个空格。
标识符命名
变量、函数和属性使用小写字母。多个单词之间用下划线
_
分隔。类中受保护的实例属性,以一个下划线开头,如
_protected = 1
。在类以外,你可以直接调用单下划线开头的属性,但并不推荐这样做。因为这种写法表示作者并不希望其他人调用这个属性,并且以后作者可能会对这个属性本身以及相关的方法进行修改,从而导致后续维护时出现意料之外的问题。类中私有的实例属性,以两个下划线开头,如
__protected = 1
。注意,在类之外,你无法直接调用双下划线开头的属性,例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class PrivateClass:
def __init__(self):
self.__private = 'I am private'
def get_private(self):
return self.__private
if __name__ == '__main__':
private = PrivateClass()
print(private.get_private())
>>>
I am private
print(private.__private)
>>>
Traceback (most recent call last):
File "XXX.py", line 12, in <module>
print(private.__private)
AttributeError: 'PrivateClass' object has no attribute '__private'. Did you mean: 'get_private'?但是,并不是说就一定无法调用。你可以通过以下方式强行调用:
1
print(private._PrivateClass__private)
但这种方法极其不推荐。紧急按钮外面的保护盒是为了防止意外按下,但并不是为了防止故意按下。不要在类外调用双下划线开头的私有属性。
类和异常的命名为每个单词的首字母大写(即驼峰命名法)。
模块级别的常量,应该用全大写字母,如果有多个单词则用下划线分隔。
类的实例方法,应该把第一个参数命名为self表示实例自身。(你会发现不叫self依然可以运行,但规范还是应该遵守。)
类的类方法,应该把第一个参数命名为cls表示类自身。
返回的用不到的变量应该用下划线表示,例如:
1
2
3
4
5
6
7
8a_list = ['a' for _ in range(5)]
def test():
return 'b', 'c'
b, _ = test()
表达式和语句
采用内联形式的否定词,而不要把否定词放在整个表达式的前面。
1
2
3
4#应该是
if a is not b:
#而不是
if not a is b:不要用检查长度的方式来判断字符串、列表等是否为None或者没有元素,应该用if not x这样的写法来检查它。
就算if分支、for循环、except异常捕获等中只有一行代码,也不要将代码和if、for、except等写在一起,分开写才会让代码更清晰。
import语句总是放在文件开头的地方。
引入模块的时候,
from math import sqrt
比import math
更好。如果有多个import语句,应该将其分为三部分,从上到下分别是Python标准模块、第三方模块和自定义模块,每个部分内部应该按照模块名称的字母表顺序来排列。
类型提示
如果时间充裕,或者编写需要给其他人看的代码,最好在代码中加入类型提示。
1 | def num2str(num: int) -> str: |
参数冒号后面的类型表明num应该是int类型,而->后面的类型表示这个函数会返回一个str类型的返回值。注意,有些类型需要导入typing才能正确表示,如列表List:
1 | from typing import List |
另外,如果函数有多种允许的参数类型或者有多种可能的返回值,用Union表示:
1 | from typing import Union |
其他一些比较特殊的类型:
1 | from typing import Any, Type, Callable, Iterable |