说明1:vscode可以下载安装插件,实现自动pep8格式化,有需要的可以去试试;
说明2:用gitlab作为代码管理工具的时候,可以在本地仓库中设置一些参数,每次commit之前,会检查自己的代码,通过了才commit成功,教程可以参考 安装使用 pre-commit
;
说明3:要了解pep8详细格式,最好还是读原文:PEP 8 – Style Guide for Python Code
;
说明4:这篇整理文档,尽量直译并选了一些要点。
文章目录
0. 每行最大列
简言之:保证每行不超过79个字符,如果开发团队喜欢更大的列数,可以扩大最多99个字符;但是保证注释最多72个字符;
Limit all lines to a maximum of 79 characters.
另
Some teams strongly prefer a longer line length. For code maintained exclusively or primarily by a team that can reach agreement on this issue, it is okay to increase the line length limit up to 99 characters, provided that comments and docstrings are still wrapped at 72 characters.
The Python standard library is conservative and requires limiting lines to 79 characters (and docstrings/comments to 72).
1. 缩进-Indentation
1.1 函数相关
# Correct:
# Aligned with opening delimiter.(括号中参数换行要对齐)
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.(如果多行且下面还有代码,要继续缩进)
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.(一开始就换行,缩进四个,且对齐)
foo = long_function_name(
var_one, var_two,
var_three, var_four)
# Wrong:
# Arguments on first line forbidden when not using vertical alignment. (换行没有对齐)
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Further indentation required as indentation is not distinguishable.(换行没有继续缩进,因为下面还有代码)
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
1.2 if 条件换行
包括不限于以下形式
# 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()
1.3 换行时结束括号的位置
(1)可以与前一行(list里的前一行)对齐
(2)与整行的开始对齐
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',
)
2. 换行
2.1 二元操作符换行位置——放到每行开头
# 错误:
# operators sit far away from their operands (错误原因:每行的二元符应放到每行开始)
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
# 正确:
# easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
3. 空白行-Blank Lines
(1)Surround top-level function and class definitions with two blank lines.(class定义和top-level函数前后空两行)
(2)Method definitions inside a class are surrounded by a single blank line.(class的方法空一行)
(3)Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).Use blank lines in functions, sparingly, to indicate logical sections.
(4)Python accepts the control-L (i.e. ……L) form feed character as whitespace; Many tools treat these characters as page separators, so you may use them to separate pages of related sections of your file. Note, some editors and web-based code viewers may not recognize control-L as a form feed and will show another glyph in its place. 【一个比较好理解的翻译如下:Python接受contol-L(即^L)换页符作为空格;Emacs(和一些打印工具) 视这个字符为页面分割符,因此在你的文件中,可以用他们来为相关片段(sections)分页。注意,一些编辑器和基于Web的代码查看器可能不能识别control-L是换页,将显示另外的字形(来源:https://www.jianshu.com/p/28f191f97e6f)】
4. 导入-import
4.1 一行import一个,除了from…import…
# 正确:
import os
import sys
# 错误:
import sys, os
# 正确:
from subprocess import Popen, PIPE
4.2 所有import的包分成三组
(1)import 标准包
(2)import 相关的第三方包
(3)import 本地包或模块
以上三组以一个空白行分隔。
4.3 推荐用绝对路径导入
4.4 避免使用 from import *
可能会导致命名冲突。
5. 空格
5.1 和各种括号相邻——不加空格
# 正确:
spam(ham[1], {eggs: 2})
# 错误:
spam( ham[ 1 ], { eggs: 2 } )
5.2 逗号和结束括号之间——其实是5.1的特例
# 正确:
foo = (0,)
# 错误:
bar = (0, )
# 正确:
if x == 4: print(x, y); x, y = y, x
# 错误:
if x == 4 : print(x , y) ; x , y = y , x
5.3 数组的切片操作
对于数组的切片操作(从下述范例代码可以总结出规律):
(1)如果切片坐标都是数字或者变量,则没有空格;
(2)如果切片坐标是表达式(如范例中加法或者函数式),则当做普通表达式,冒号两边要加空格;
# 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 : : upper]
ham[ : upper]
5.4 多个操作符
如果表达式内有多个优先级的操作符,在优先级最低的那个两边加空格。
# Correct:
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
# Wrong:
x = x * 2 - 1 # 错误原因:有 * 和 - 两种操作符,在优先级最低(-)两边加空格
hypot2 = x * x + y * y # 错误原因:+ 优先级最低,两边加空格
c = (a + b) * (a - b) # 错误原因:因为有括号,*是优先级最低的,因此*两边加空格
5.5 函数参数中等号两边不加空格
# 正确:
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(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# 错误:
def munge(input: AnyStr=None): ... # 错误原因:参数注释中的默认参数的 = 两边加空格
def munge(input: AnyStr, limit = 1000): ... # 错误原因:普通参数的默认值 = 两边不加空格
5.6 不鼓励同一行有多个语句
# 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()
绝对不要:
# 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()
6. 注释-comment
(1)英文注释,首字母大写;
(2)注释符号#后要加空格再写注释;【这一条是我自己看很多python包里面的这么写的】
(3)少用行内注释,尤其是该行内容较明显时;
例如
x = x + 1 # Increment x
7. docstrings
如果docstring只有一行,则所有符号也在一行,例如:
"""Return an ex-parrot."""
8. 命名约定-Naming Conventions
Python库的命名约定有点混乱,所以我们永远无法做到完全一致——不过,以下是目前推荐的命名标准。
8.1 Overriding Principle
Names that are visible to the user as public parts of the API should follow conventions that reflect usage rather than implementation.
8.2 命名风格-描述性的(Descriptive: Naming Styles)
(1)如果名称中有缩略词,所有缩略词大写:例如HTTPServerError 好于HttpServerError;
(2)Capitalized_Words_With_Underscores 是很丑的写法;
(3)_single_leading_underscore: 下划线开始的是内部使用的函数,from M import 不会导入这种函数;
(4)single_trailing_underscore_: 避免命名冲突;
(5)__name:双下划线开头是私有变量或者私有函数,防止用户误改这些量;可以参考https://blog.csdn.net/zhu_liangwei/article/details/7667745;
(6)__name__:双下划线开始和结束,避免制造这种命名,一般是python自带的命名。
8.3 命名规范-规定的(Prescriptive: Naming Conventions)
8.3.1 避免使用的命名
避免使用:“l”(小写L)、“O”(大写O)、“I”(大写i)这些容易混淆的单字母作为变量。
8.3.2 包名或者模块名-Package and Module Names
原文说的很清楚:模块名和包名都是用小写字母和下划线,模块名要尽量短,包名要避免使用下划线。
(Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.)
8.3.3 类名称-Class Names
类名称:通常用CapWords格式,亦即每个单词都是大写字母开头的格式。
(Class names should normally use the CapWords convention.)
8.3.4 函数名和变量名
函数名和变量名,都用以下划线"_"连接的小写单词组成;
除非和已有的内置包重名比如thread.py。
8.3.5 常数
常数通常用全大写字母表示,如果有多个单词,用下划线连接。
9. 编程建议-Programming Recommendations
(1)和singletons(比如None)进行比较时,避免用 ==,而是应该用 is 或者 is not;
(2) try: … except Error: … 的时候,尽量避免只用一个光秃秃的 except,尽量加上错误类型;
(3)用string.startswith()和string.endswith()来代替用字符串下标来取值;
(4)判断对象类型,用isinstance 而不是用两个type相等;
(5)判断list之类的是否是空时,
# Correct:
if not seq:
if seq:
# Wrong:
if len(seq):
if not len(seq):
(6)判断boolean类型是True或者False,不用 == 来判断;
Don’t compare boolean values to True or False using ==:
# Correct:
if greeting:
# Wrong:
if greeting == True:
Worse:
# Wrong:
if greeting is True: