Python3基础教程(十五)—— PEP8 代码风格指南
编程语言不是艺术,而是工作或者说是工具,所以整理并遵循一套编码规范是十分必要的。 这篇文章原文实际上来自于这里:https://www.python.org/dev/peps/pep-0008/
有很多规范,这里只讲其中一部分。
代码排版
缩进
每层缩进使用4个空格。
续行要么与圆括号、中括号、花括号这样的被包裹元素保持垂直对齐,要么放在 Python 的隐线(注:应该是相对于def的内部块)内部,或者使用悬挂缩进。使用悬挂缩进的注意事项:第一行不能有参数,用进一步的缩进来把其他行区分开。
好的:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four) # More indentation included to distinguish this 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)
不好的:
# 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)
4空格规则是可选的:
# Hanging indents *may* be indented to other than 4 spaces.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
当 if 语句的条件部分足够长,需要将它写入到多个行,值得注意的是两个连在一起的关键字(i.e. if),添加一个空格,给后续的多行条件添加一个左括号形成自然地4空格缩进。如果和嵌套在 if 语句内的缩进代码块产生了视觉冲突,也应该被自然缩进4个空格。这份增强建议书对于怎样(或是否)把条件行和 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()
在多行结构中的右圆括号、右中括号、右大括号应该放在最后一行的第一个非空白字符的正下方,如下所示:
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',
)
制表符还是空格?
空格是首选的缩进方法。
制表符(Tab)应该被用在那些以前就使用了制表符缩进的地方。
Python 3 不允许混合使用制表符和空格来缩进代码。
混合使用制表符和空格缩进的 Python 2 代码应该改为只使用空格。
当使用-t
选项来调用 Python 2 的命令行解释器的时候,会对混合使用制表符和空格的代码发出警告。当使用-tt
选项的时候,这些警告会变成错误。这些选项是强烈推荐的!
每行最大长度
限制每行的最大长度为79个字符。
对于那些约束很少的文本结构(文档字符串或注释)的长块,应该限制每行长度为72个字符。
限制编辑窗口的宽度使并排打开两个窗口成为可能,使用通过代码审查工具时,也能很好的通过相邻列展现不同代码版本。
一些工具的默认换行设置打乱了代码的可视结构,使其更难理解。限制编辑器窗口宽为80来避免自动换行,即使有些编辑工具在换行的时候会在最后一列放一个标识符。一些基于 Web 的工具可能根本就不提供动态换行。
一些团队更倾向于长的代码行。对于达成了一致意见来统一代码的团队而言,把行提升到80~100的长度是可接受的(实际最大长度为99个字符),注释和文档字符串的长度还是建议在72个字符内。
Python 标准库是非常专业的,限制最大代码长度为79个字符(注释和文档字符串最大长度为72个字符)。
首选的换行方式是在括号(小中大)内隐式换行(非续行符\
)。长行应该在括号表达式的包裹下换行。这比反斜杠作为续行符更好。
反斜杠有时仍然适用。例如,多个很长的with
语句不能使用隐式续行,因此反斜杠是可接受的。
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
(见前面关于多行if
语句的讨论来进一步思考这种多行with
语句该如何缩进)
另一种使用反斜杠续行的案例是assert
语句。
确保续行的缩进是恰到好处的。遇到二元操作符,首选的断行位置是操作符的后面而不是前面。这有一些例子:
class Rectangle(Blob): def __init__(self, width, height,
color='black', emphasis=None, highlight=0):
if (width == 0 and height == 0 and
color == 'red' and emphasis == 'strong' or
highlight > 100):
raise ValueError("sorry, you lose")
if width == 0 and height == 0 and (color == 'red' or
emphasis is None):
raise ValueError("I don't think so -- values are %s, %s" %
(width, height))
Blob.__init__(self, width, height,
color, emphasis, highlight)
空行
顶级函数和类定义上下使用两个空行分隔。
类内的方法定义使用一个空行分隔。
可以使用额外的空行(有节制的)来分隔相关联的函数组。在一系列相关联的单行代码中空行可以省略(e.g. 一组虚拟的实现)。
在函数中使用空白行(有节制的)来表明逻辑部分。
Python 接受使用换页符(i.e. Ctrl+L
)作为空格;许多工具都把Ctrl+L
作为分页符,因此你可以用它们把你的文件中相似的章节分页。注意,一些编辑器和基于 Web 的代码查看工具可能不把Ctrl+L
看做分页符,而是在这个位置放一个其它的符号。
源文件编码
在核心 Python 发布版中的代码应该总是使用UTF-8
编码(或者在 Python 2 中使用ASCII
)。
使用ASCII
(Python 2)或UTF-8
(Python 3)的文件不需要有编码声明(注:它们是默认的)。
在标准库中,非缺省的编码应该仅仅用于测试目的,或者注释或文档字符串中的作者名包含非ASCII
码字符;否则,优先使用\x
、\u
、\U
或者\N
来转义字符串中的非ASCII
数据。
对于 Python 3.0 和之后的版本,以下是有关标准库的政策(见PEP 3131):所有 Python 标准库中的标识符必须使用只含ASCII
的标识,并且应该使用英语单词只要可行(在多数情况下,缩略语和技术术语哪个不是英语)。此外,字符串和注释也必须是ASCII
。仅有的例外是:(a)测试用例测试非ASCII
特性时,(b)作者名。作者的名字不是基于拉丁字母的必须提供他们名字的拉丁字母音译。
导入包
import不同的模块应该独立一行,如:
好的:
import os
import sys
不好的:
import sys, os
这样也是可行的:
from subprocess import Popen, PIPE
import
语句应该总是放在文件的顶部,在模块注释和文档字符串之下,在模块全局变量和常量之前。
import
语句分组顺序如下:
- 导入标准库模块
- 导入相关第三方库模块
- 导入当前应用程序/库模块
每组之间应该用空行分开。
然后用__all__
声明本文件内的模块。
绝对导入是推荐的,它们通常是更可读的,并且在错误的包系统配置(如一个目录包含一个以os.path
结尾的包)下有良好的行为倾向(至少有更清晰的错误消息):
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
当然,相对于绝对导入,相对导入是个可选替代,特别是处理复杂的包结构时,绝对导入会有不必要的冗余:
from . import sibling
from .sibling import example
标准库代码应该避免复杂的包结构,并且永远使用绝对导入。
应该从不使用隐式的相对导入,而且在 Python 3 中已经被移除。
从一个包含类的模块导入类时,这样写通常是可行的:
from myclass import MyClass
from foo.bar.yourclass import YourClass
如果上面的方式会本地导致命名冲突,则这样写:
import myclass
import foo.bar.yourclass
以myclass.MyClass
和foo.bar.yourclass.YourClass
这样的方式使用。
应该避免通配符导入(from import *
),这会使名称空间里存在的名称变得不清晰,迷惑读者和自动化工具。这里有一个可辩护的通配符导入用例,,重新发布一个内部接口作为公共 API 的一部分(例如,使用纯 Python 实现一个可选的加速器模块的接口,但并不能预知这些定义会被覆盖)。
字符串引号
在 Python 里面,单引号字符串和双引号字符串是相同的。这份指南对这个不会有所建议。选择一种方式并坚持使用。一个字符串同时包含单引号和双引号字符时,用另外一种来包裹字符串,而不是使用反斜杠来转义,以提高可读性。
对于三引号字符串,总是使用双引号字符来保持与文档字符串约定的一致性(PEP 257)。
表达式与语句中的空格
避免在下列情况中使用多余的空格:
- 与括号保持紧凑(小括号、中括号、大括号):
Yes: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
- 与后面的逗号、分号或冒号保持紧凑:
Yes: if x == 4: print x, y; x, y = y, x
No: if x == 4 : print x , y ; x , y = y , x
- 切片内的冒号就像二元操作符一样,任意一侧应该被等同对待(把它当做一个极低优先级的操作)。在一个可扩展的切片中,冒号两侧必须有相同的空格数量。例外:切片参数省略时,空格也省略。
好的:
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]
不好的:
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
- 函数名与其后参数列表的左括号应该保持紧凑:
Yes: spam(1)
No: spam (1)
- 与切片或索引的左括号保持紧凑:
Yes: dct['key'] = lst[index]
No: dct ['key'] = lst [index]
- 在赋值操作符(或其它)的两侧保持多余一个的空格:
好的:
x = 1
y = 2
long_variable = 3
不好的:
x = 1
y = 2
long_variable = 3
其它建议
总是在这些二元操作符的两侧加入一个空格:赋值(=),增量赋值(+=, -= etc.),比较(==, <, >, !=, <>, <=, >=, in, not in, is, is not),布尔运算(and, or, not)。
在不同优先级之间,考虑在更低优先级的操作符两侧插入空格。用你自己的判断力;但不要使用超过一个空格,并且在二元操作符的两侧有相同的空格数。
好的:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
不好的:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
- 不要在关键值参数或默认值参数的等号两边加入空格。
好的:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
不好的:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
- 【注:Python 3】带注释的函数定义中的等号两侧要各插入空格。此外,在冒号后用一个单独的空格,也要在表明函数返回值类型的
->
左右各插入一个空格。
好的:
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:
- 打消使用复合语句(多条语句在同一行)的念头。
好的:
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
不好的:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
- 有时候把
if/for/while
和一个小的主体放在同一行也是可行的,千万不要在有多条语句的情况下这样做。此外,还要避免折叠,例如长行。
好的:
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()
不好的:
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()
注释
注释应该是完整的句子。如果注释是一个短语或语句,第一个单词应该大写,除非是一个开头是小写的标识符(从不改变标识符的大小写)。
如果注释很短,末尾的句点可以省略。块注释通常由一个或多个有完整句子的段落组成,并且每个句子应该由句点结束。
你应该在一个句子的句点后面用两个空格。
写英语时,遵循《Strunk and White》(注:《英文写作指南》,参考维基百科)。
块注释
块注释通常用来说明跟随在其后的代码,应该与那些代码有相同的缩进层次。块注释每一行以#
起头,并且#
后要跟一个空格(除非是注释内的缩进文本)。
行内注释
有节制的使用行内注释。
一个行内注释与语句在同一行。行内注释应该至少与语句相隔两个空格。以#
打头,#
后接一个空格。
无谓的行内注释如果状态明显,会转移注意力。不要这样做:
x = x + 1 # Increment x
但有的时候,这样是有用的:
x = x + 1 # Compensate for border
文档字符串
编写良好的文档字符串(a.k.a “docstring”)的约定常驻在 PEP 257
- 为所有的公共模块、函数、类和方法编写文档字符串。对于非公共的方法,文档字符串是不必要的,但是也应该有注释来说明代码是干什么的。这个注释应该放在方法声明的下面。
- PEP 257 描述了良好的文档字符串的约定。注意,文档字符串的结尾
"""
应该放在单独的一行,例如:
"""Return a foobang Optional plotz says to frobnicate the bizbaz first.
"""
- 对于单行的文档字符串,把结尾
"""
放在同一行。
版本注记
如果必须要 Subversion,CVS 或 RCS 标记在你的源文件里,像这样做:
__version__ = "$Revision$"
# $Source$
这几行应该在模块的文档字符串后面,其它代码的前面,上下由一个空行分隔。
参考链接:https://www.shiyanlou.com/courses/596
Python3基础教程(十五)—— PEP8 代码风格指南的更多相关文章
- python的PEP8 代码风格指南
PEP8 代码风格指南 这篇文章原文实际上来自于这里:https://www.python.org/dev/peps/pep-0008/ 知识点 代码排版 字符串引号 表达式和语句中的空格 注释 版本 ...
- css3基础教程十六变形与动画animation
前面我们讲过的变形与动画一般都是通过鼠标的单击.获得焦点,被点击或对元素进行一定改变后以后触发效果的,那么有没有像Flash一样自动播放的动画效果呢?答案当然是肯定的,这就是我们今天要讲到的anima ...
- webpack4 系列教程(十五):开发模式与webpack-dev-server
作者按:因为教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步<webpack4 系列教程(十五):开发模式与 webpack-dev-server>原文地址.更欢迎来我的 ...
- Python3基础(十二) 学习总结·附PDF
Python是一门强大的解释型.面向对象的高级程序设计语言,它优雅.简单.可移植.易扩展,可用于桌面应用.系统编程.数据库编程.网络编程.web开发.图像处理.人工智能.数学应用.文本处理等等. 在学 ...
- Bootstrap <基础二十五>警告(Alerts)
警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个 ...
- 无废话ExtJs 入门教程十五[员工信息表Demo:AddUser]
无废话ExtJs 入门教程十五[员工信息表Demo:AddUser] extjs技术交流,欢迎加群(201926085) 前面我们共介绍过10种表单组件,这些组件是我们在开发过程中最经常用到的,所以一 ...
- python基础教程项目五之虚拟茶话会
python基础教程项目五之虚拟茶话会 几乎在学习.使用任何一种编程语言的时候,关于socket的练习从来都不会少,尤其是会写一些局域网的通信的东西.所以书上的这个项目刚好可以练习一下socket编程 ...
- Objective-C 基础教程第五章,复合
目录 Objective-C 基础教程第五章,复合 什么是复合? Car程序 自定义NSLog() 存取方法get Set Tires(轮胎) 存取方法 Car类代码的其他变化 扩展Car程序 复合还 ...
- PythonStudy——PyCharm 选择性忽略PEP8代码风格警告信息
用了几天的PyCharm,发现确实在编写Python代码上非常好用,但有一点体验不太好,就是代码编写时要按照PEP8代码风格编写,不然会有波浪线的警告信息.解决方法如下: 方法一:将鼠标移到提示的地方 ...
随机推荐
- 小K的农场(差分约束)
题目大意 n个点 m条描述 农场 a 比农场 b 至少多种植了 c 个单位的作物. 农场 a 比农场 b 至多多种植了 c 个单位的作物. 农场 a 与农场 b 种植的作物数一样多. 题解 差分约束裸 ...
- mysql负载均衡方案
mysql负载均衡方案 一.直接连接 数据库的读写分离方案很多,这里介绍基于mysql数据库的读写分离方案. 比较常见的读写分离方案如下: 1 基于查询分离 最简单的分离方法是将读和写分发到主和从服务 ...
- bzoj2616
树形dp+笛卡尔树+单调栈 这道题跟树形dp有什么关系? 事实上,我们对矩形建立笛卡尔树,先找出最矮的矩形,向两边区间最矮的矩形连边,这样就构成了一棵二叉树,因为只有一个矮的区间会对高的区间造成影响, ...
- 6-10 SVM支持向量机1
都是特征加上分类器.还将为大家介绍如何对这个数据进行训练.如何训练得到这样一组数据. 其实SVM支持向量机,它的本质仍然是一个分类器.既然是一个分类器,它就具有分类的功能.我们可以使用一条直线来完成分 ...
- LuoguP2822 组合数问题(组合数,二维前缀和)
P2822 组合数问题 输入输出样例 输入样例#1: 复制 1 2 3 3 输出样例#1: 复制 1 输入样例#2: 复制 2 5 4 5 6 7 输出样例#2: 复制 0 7 说明 [样例1说明] ...
- Adore
(非公共题目) 问题描述 小 w 偶然间⻅到了一个 DAG.这个 DAG 有 m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有 k 个节点. 现在小 w 每次可以取反第 i(1 &l ...
- 屏蔽QQ黄钻官方团队送礼物的方法
按照在网上查到的方法: 登录手机QQ \(\longrightarrow\) 好友动态 \(\longrightarrow\) 个人主页 \(\longrightarrow\) 右上角三道杠 \(\l ...
- ngxin做http强制跳转https,接口的POST请求变成GET
http强制跳转https出现了问题.修改nginx配置如下即可解决: server { listen 80; server_name *.snsprj.cn; return 307 https:// ...
- hive的使用 + hive的常用语法
本博文的主要内容有: .hive的常用语法 .内部表 .外部表 .内部表,被drop掉,会发生什么? .外部表,被drop掉,会发生什么? .内部表和外部表的,保存的路径在哪? .用于创建一些临时表存 ...
- Android SDK Manager 无法下载Android8.1.0(API 27) SDK Platform
在Android SDK Manager 中安装Android 8.1.0 SDK Platform时报错导致无法安装. 错误信息:Downloading SDK Platform Android 8 ...