Python实践21-PEP 8代码规范整理

PEP 8是Python的编码规范,PyCharm里面内置了基于PEP 8的代码检查功能。在项目目录上右键鼠标,选择”Inspect Code”就可以方便地进行代码静态检查。

一致性考虑

Guido的关键点之一是:代码更多是用来读而不是写。本指南旨在改善Python代码的可读性。

代码布局

  • 缩进。4个空格的缩进,不使用Tab,更不能混合使用Tab和空格。
  • 每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。
  • 顶层函数和类之间使用两个空行。
  • 类的方法之间使用一个空行。
  • (谨慎地)使用额外的空白行来分隔一组相关的函数。一堆相关的单行代码之间的空白行可以省略(例如,一组dummy implementations)。
  • 在函数中使用空行来(谨慎地)表示不同的逻辑段落。

编码

  • Python 3.0 和以后的版本,首选 UTF-8

导入

  • 导入通常应当使用单独的行
  • 导入总是位于文件的顶部,在模块注释和文档字符串之后,在模块的全局变量与常量之前。
  • 导入应该按照以下的顺序分组:
    • standard library imports 标准库导入
    • related third party imports 相关第三方导入
    • local application/library specific imports 本地应用程序/库的特定导入
  • 每组导入之间使用空行隔开。
  • 在导入之后放置任何相关的 all 说明书。
  • 非常不推荐在包内导入中使用相对路径导入。对所有导入来说,总是使用绝对包路径导入。

文档编排

  • 模块内容的顺序:模块说明和docstring—import—globals&constants—其他定义。
  • 其中import部分,又按标准、第三方和自己编写顺序依次排放,之间空一行。
  • 不要在一句import中多个库,比如import os, sys不推荐。
  • 如果采用from XX import XX引用库,可以省略‘module.’,都是可能出现命名冲突,这时就要采用import XX。

空格的使用

  • 总体原则,避免不必要的空格。
  • 括号里边避免空格。
  • 逗号、冒号、分号前不要加空格。
  • 函数的左括号前不要加空格。如Func(1)。
  • 索引操作中的冒号当作操作符处理前后要有同样的空格(一个空格或者没有空格)
  • 操作符左右各加一个空格,不要为了对齐增加空格。
  • 函数调用的左括号之前不能有空格
  • 二元运算符两边放置一个空格
  • 不要将多句语句写在同一行,尽管使用‘;’允许。
  • 通常不推荐复合语句(Compound statements: 多条语句写在同一行)。

注释

  • 不好理解的注释不如没有注释。注释要和代码保持与时俱进!
  • 注释应该是一条完整的句子。如果注释是一个短语或句子,它的第一个字应该大写,除非它是一个小写字母开头的标识符(绝对不要改变标识符的大小写)。
  • 如果注释很短,那么结尾的句号可以省略。块注释通常由一个或多个段落组成, 这些段落由完整的句子构成,每个句子都应该使用句号结尾。
  • 句号结尾的句子后面应该有2个空格。
  • 来自非英语国家的Python程序员:请使用英语写注释,除非你120%肯定你的代码将永远不会被不说你的语言的人阅读。
  • 块注释在一些(或全部)代码之前,并和代码缩进一致。每行注释均以 # 开头,然后紧跟一个空格(除非在注释内缩进)
  • 块注释内的段落使用仅含 # 的单行分隔。
  • 谨慎地使用内嵌注释:内嵌注释是一种和语句在同一行的注释。内嵌注释至少和语句间隔2个空格。他们开始于一个 # 和一个空格。
  • 如果语句显而易见,那么内嵌注释是不必要的,实际上会让开发者分心。
  • 所有的Public模块,函数,类和方法都需要编写文档字符串。对非公共的方法而言,文档字符串则不是必要的,但是可以使用一个注释来描述这个方法。这个注释必须位于 def 行之后。
  • 注意最重要的是,””” 作为多行的文档字符串的结束,应该单独一行
  • 对单行的文档字符串来说,结尾的 “”” 在同一行。

命名规范

  • 总体原则,新编代码必须按下面命名风格进行,现有库的编码尽量保持风格。
  • 永远不要使用 ‘l’(小写的L),’O’(大写的O),或者’I’(大写的I)作为单字变量名。
  • 在某些字体中,这些字很难和数字的0 和 1 区分。当打算用’l’的时候,用’L’来代替。
  • 模块应该用简短的,全小写的名字。如果能增强可读性的话,可以使用下划线。
  • Python的包也要用全小写的,短名称,但是不建议用下划线。
  • 毫无例外,类的命名使用CapWords的方式,模块内部使用的类采用_CapWords的方式。
  • 异常也是类,所以这里也用类名规则。但是,你异常名应该用后缀 “Error”(如果你的异常确实是个错误的话)。
  • 被设计为通过from M import *导入的模块。应该用__all__机制来防止导出全局。或者使用过去的全局变量前置下划线的规则(这是为了说明这些变量是”模块私有的”)。
  • 函数名应该用小写,为了增加可读性可以用下划线分隔。
  • 全局变量名(我们希望这些变量只在模块内部使用)和函数规则一样。
  • 始终用self作为实例方法的第一个参数。
  • 始终用cls作为类方法的第一个参数。
  • 如果函数的参数名和保留字冲突。用结尾下划线比缩写或是滥用的组词更好。因此 class_ 比 clss好。(也许,更好的避免冲突的方式是用同义词。)
  • 方法名和实例变量:使用函数命名规则:使用下划线分隔的小写字母会提高可读性。
  • 只在私有方法和实例变量前用单下划线。
  • 常量通常在模块级别中定义,用全大写和下划线分隔的字符来编写。例如MAX_OVERFLOW 和 TOTAL。

设计建议

  • 总要考虑一个类的方法或实例变量(总体而言:属性)应该是公用的或者非公用的。如果不能确定的话,设计为私有的。 因为,之后将一个私有的改为公有的要比将公有的变为私有的容易。
  • 公有属性,是你希望与这个类无关的客户使用的,并通过你的委托机制来避免由于属性变更导致的向后不兼容。 私有属性,是你不希望被第三方使用的。你不能保证私有属性不会改变甚至被删除。
  • 代码应该用不损害其他Python实现的方式去编写(PyPy, Jython, IronPython, Cython, Psyco 等)。例如,不要依赖于CPython的高效内置字符连接语句a += b or a = a + b.这些语句在Jython中运行较慢。在性能敏感的库中,应该用”.join() 来取代。这样可以保证在不同的实现中,字符链接花费的时间都呈线性。
  • 与诸如None这样的字符比较时,要使用is or is not,永远不要用等于操作。 同样地,在测试一个变量或参数默认值为None被设置为其他值时(比如if x表示if x is not None时),要注意。 这个值应该有一个能在布尔逻辑的上下文中为false的类型(比如容器)。
  • 当用复杂比较实现排序操作时,最好去实现全部六个操作(eqneltlegtge),而不是依靠其他的代码去实现一些怪异的比较。为了最大程度的减少实现这一过程的开销。functools.total_ordering()提供了生成缺少的比较操作的方法。
  • 使用基于对象的异常。模块或者包应该定义自己的异常基类,这个类应该继承自内置的Exception类。总要包含类文档语句。在这里用到类命名规范。尽管当你的“异常”是一个“错误”(error)时,你应该在自己的异常类加上后缀”Error”。 非错误类(Non-error)异常,不需要特别的后缀。
  • 当抛出一个异常的时候,使用raise ValueError(‘message’)代替旧的raise ValueError, ‘message’格式。
  • 当捕获一个异常的时候,要用详细异常声明代替光秃秃的except: 语句.
  • 使用”.startswith() 和 ”.endswith()而非字符切片去检测前缀或后缀。
  • 对象类型比较总要用 isinstance() 而非直接比较
  • 检查序列为空: if not seq: 或者 if seq:
  • 别用‘==’进行布尔值和 True 或者 False 的比较