Python PEP 8 简单汇总
PEP 8 是Python的代码风格指南(Style Guide for Python Code),其中很多内容都来自Guido van Rossum。PEP 8 从代码格式、注释、空白、变量名、参考及权利声明等方面出发,主要提到了以下这些关于Python代码风格的问题。
代码格式(Code lay-out)
缩进(Indentation)
每一级缩进使用4个空格。当一行过长需要折行时,应该保持与换行的界定符的垂直对齐。如下例:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
或者下一行采用8个空格的缩进,与其他的正常缩进区别开来,例如:
# More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
悬挂的缩进应该保持一致。
如果if
语句太长以至于需要分成多行书写,应该把if
和一个空格以及一个左括号和在一起,形成一个自然地4个空格的缩进。但也可以让下一行多缩进4个空格(8个空格的缩进)。同时,还可以添加一些注释使得代码更清楚。例如以下几种写法:
# 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()
如果列表性质的内容需要拆成多行,那么右括号应该在新的一行同列表的上一行内容的第一个字符保持对齐或者同多行语句的开始位置保持对齐,如下例:
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',
)
制表符与空格(Tabs or Spaces?)
应当使用空格来缩进,Tab键仅仅用于那些已经采用Tab键来缩进的Python源代码文件。
Python 3 不允许混用Tab键和空格来缩进。对于Python 2,混用空格键和Tab键来缩进的代码应当被递归地转换成仅仅使用空格来缩进。
Python 2 的交互式命令行有-t
选项来检查不合理的混用Tab键和空格的缩进。当使用-tt
选项时,这些相关的警告将会变成错误。强烈建议使用这些选项。
每行最长长度(Maximum Line Length)
每行的最长长度限制应该设置为79个字符。对于类似docstrings
或者comments
(文档字符串或注释)的缺乏结构的文本块应当限制在每行72个字符。
空行(Blank Lines)
用两个空行来分隔顶层函数和类。用一个空行来分隔类里面定义的函数。此外,还需要额外的空行来分隔相关的几个函数。
Python允许把Ctrl-L
符号当成空白,这在一些文本工具中表示分页符。注意,一些文本编辑器可能不能正确识别Ctrl-L
符号,并把它当成某个奇怪的象形文字。
源代码文件编码(Source File Encoding)
Python代码应当使用UTF-8编码(Python 2使用 ASCII)。
使用 ASCII编码的Python 2 代码文件和使用 UTF-8 编码的Python 3 代码文件应该不使用编码声明。
Python 可以使用如下格式的注释来声明文件的编码:
# -*- coding: <encoding name> -*-
或者:
# -*- coding=<encoding name> -*-
Import格式(Import)
-
多个 import 声明应该分行来写。
例如:
import os import sys
而不是写成
import os, sys
从同一个模块中 import 多个函数等时可以写成一行。例如
from subprocess import Popen, PIPE
-
import 声明应该放在文件的最上方。也就是模块注释和文档字符串之后,模块全局变量和常量之前的位置。
多个import声明应该使用如下顺序组织:
- 标准库(standard library imports)
- 相关的第三方库(related third party imports)
- 本地应用和库(local application/library specific imports)
每一组import声明之间应该用一个空行隔开。
将任何
__all__
说明都放在import声明之后。 -
推荐使用绝对引入(absolute import),这样代码可读性更好,并且当引入的库存在错误时,代码表现得会更好(至少会生成更有用的错误信息)。
例如:
import mypkg.sibling from mypkg import sibling
隐含的相对路径引入也是可以接受的。例如:
from . import sibling from .sibling import example
-
当从一个包含class的module中import一个类时,应当这样书写:
from myclass import MyClass from foo.bar.yourclass import YourClass
如果这会导致与本地的变量名冲突,那么,这样的方式也是可行的:
import myclass import foo.bar.yourclass
-
应该避免使用通过通配符import的方式(
from <module> import *
)。这会导致命名空间的混淆,并对一些库和工具造成误解。
引号(String Quotes)
在Python中,使用双引号和使用单引号表示的字符串没有区别。只要制定一条原则并在整个项目的所有代码中保持一致即可。
当字符串中包含单引号时,使用单引号,反之,当字符串中包含单引号时,使用双引号。
空白符(Whitespace)
在下列情形下应该避免多余的空格:
-
括号内紧挨着括号不要留空格
-
紧挨着冒号,逗号或分号前面
然而,当冒号表现得像一个二元操作符,例如在列表切片(slice)等场合下,冒号左右应该留下相同个数的空格,如下例:
ham[1:9] ham[lower+offset : upper+offset]
-
函数名与左括号之间不要留空格
-
字典、元组、列表等变量名和左方括号之间不要留空格
-
定义变量或赋值时不要用空格去对齐等号。
例如:
x = 1 y = 2 long_variable = 3
不要写成:
x = 1 y = 2 long_variable = 3
-
在函数的默认参数的等号左右和通过命名参数调用函数的等号左右不要留空格。
例如:
def complex(real, imag=0.0): return magic(r=real, i=imag)
不要写成:
def complex(real, imag = 0.0): return magic(r = real, i = imag)
在以下这些情形下,应当使用空格
-
要在注解函数定义的等号两侧使用空格。此外,还应该在注解函数定义中的冒号”:”后边使用空格,在”->”两边使用空格。
例如:
def munge(input: AnyStr): def munge(sep: AnyStr = None): def munge() -> AnyStr: def munge(input: AnyStr, sep: AnyStr = None, limit=1000):
不要写成:
def munge(input: AnyStr=None): def munge(input:AnyStr): def munge(input: AnyStr)->PosInt:
注释(Comments)
块注释(Block Comments)
块注释的缩进应当与代码的缩进保持一致。在#
后边要加一个空格。
行内注释(内联注释)(Inline Comments)
行内注释跟代码语句应该保持至少2个空格的距离。并且,要在#
后边加一个空格。
文档字符串(Documentation Strings)
应该给所有的公有模块、函数、类、方法写文档字符串。文档字符串应该写在def ...
语句之后一行。
PEP 257 描述了好的文档字符串的写法。
文档字符串格式示例:
"""Return ...
......
"""
对于一行的文档字符串,应该把两个"""
写在同一行。
版本标记(Version Bookkeeping)
如果需要在代码中描述版本信息,应该写成如下格式:
__version__ = "$Revision$"
# $Source$
这些代码应该写在文档字符串之后,代码之前,并且前后都要用一个空行分开。
命名约定(Naming Conventions)
Overriding Principle
公有API部分的命名应该能够反映用途而非实现方式。
Descriptive: Name Style
采用描述性的命名风格。其中,有些形式的命名应该遵循如下约定:
-
_single_leading_undersrore
:使用的标识符(“internal use” indicator)。
例如,
from M import *
就不会import名字以一个下划线开头的的对象(objects)。 -
single_trailing_underscore
:这项约定用来避免与Python的关键字(keywords)冲突。例如:
Tkinter.Toplevel(master, class_ = 'ClassName')
-
__double_leading_underscore
:这用来命名类属性(class attribute)。
-
__double_leading_and_trailing_underscore__
:用在用户控制的(user-controlled)的命名空间下。从不创造这样的变量名,仅仅使用那些文档中存在的。
Prescriptive: Naming Conventions
Names to Avoid
应当避免使用”l”, “O”, “I”作为单个字母的变量名。
包和模块的命名
模块应该采用较短的、全部为小写字母的命名。如果下划线可以增强名字的可读性,那么可以用在模块名中。
异常命名(Exception Names)
对异常的命名应当包含后缀”Error”。
类的方法(method)的命名
使用self
作为实例方法(instance methods)的第一个参数。
使用cls
作为类方法(class methods)的第一个参数。
常量
常量的命名应该全部采用大写字母。
全局变量
对于包和模块,可以通过设置__all__
的内容来指定接口(API)。
其他的约定
lambda和def
定义函数时,使用def
。不要把lambda
表达式绑定到标识符。
自定义异常
自定义异常时,直接继承Exception
而不是BaseException
。
合理使用异常链
捕获异常
捕获异常时,尽量指明是什么类型的异常而不要全都是用单单的except:
。
finally
如果代码需要做清理工作,要加上 finally
语句块。
字符串检查
使用startwith()
和endwith()
方法而不是字符串切片(string slicing)来检查字符串的前缀和后缀。
类型检查
使用isinstance()
而不是type() ==
来检查变量的类型。
序列非空检查
对于序列(string, list, tuple),空列表的布尔值为False
,可以用这一特点来进行序列的非空检查,而不是判断序列的长度。