python编码风格之PEP8
一、缩进
1、用4个空格不要用使用tab,更不要混合使用
2、对于函数名较长的参数,使用如下格式:
def long_function_name(var_one, var_two,
var_three, var_four)
3、对于if等条件比较多的情况,使用如下格式,and在下面,在and前面添加缩进
if (this_is_one_thing
and that_is_another_thing):
do_something()
4、对于右括号(')'、']'、'}'),放在list的最后一行的第一个非空白字符
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
二、制表符还是空格?
永远不要将制表符与空格混合使用。Python最常用的缩进方式是只是用空格。
当调用Python命令行的 -t 选项时,它会检测并警告代码非法混合使用制表符和空格。当使用 -tt 选项时,警告变成了错误。
三、最大行长度
1、限制所有行最长为79个字符。
2、使用反斜杠来分行是一个很好的选择,当然,也可以使用括号来进行续行
3、我们应当选择在二元操作符之后进行分行,而不是之前。
四、空行
1、使用两行空行来分隔顶层函数和类定义。
2、使用单行空行来分隔类方法定义。
3、在函数中使用空行来表示不同的逻辑块。
五、编码
源代码使用UTF-8编码,即 -*- coding: utf-8 -*-
六、导入
1、每一个导入通常应当使用单独的行。
Yes: import os
import sys
No: import sys, os
It's okay to say this though:
from subprocess import Popen, PIPE
2、导入应当位于文件顶部,在模块注释和文档字符串之后,在全局变量和常量之前。
3、导入应当按以下顺序分组,且每组导入之间使用空行隔开:
1、标准库导入
2、第三方库导入
3、本地应用程序/定制库导入
Put any relevant __all__ specification after the imports.
4、建议使用绝对导入形式的 import 语句,它不仅更易读,并且在配置错误(例如某个包中的目录以 sys.path 结尾时)时有更良好的导入行为(至少有更好的报错):
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
5、当在某个包含类的模块中导入类时,通常情况下请这样写:
from myclass import MyClass
from foo.bar.yourclass import YourClass
但如果这样的书写方式引起类名和本地名字冲突,则请这样书写:
import myclass
import foo.bar.yourclass
并使用 “myclass.MyClass” 和 “foo.bar.yourclass.YourClass” 来对其进行引用。
6、通配符导入(from <module> import *)应该被禁止,因为这样做会导致在被导入的命名空间中存在哪些命名对象变得不清晰,迷惑读者与其他自动化工具。不过要使用通配符导入,也有站得住脚的理由:需要将内部 API 重新发布为公共 API(例如,使用纯 Python 重写一个可选加速模块的接口,而事先你并不知道这个接口将被重写)。
六、引号
1、单引号和双引号功能是一样的,但在程序中,选定一种使用,不要混用
2、如果程序中包含普通的单引号或双引号字符,用另一种引号来进行引用
3、用于多行docstring的三引号,使用三个双引号表示
七、眼中钉
在以下情况中避免使用额外的空格:
#符合约定的代码
spam(ham[1], {eggs: 2})
#不符合约定的代码
spam( ham[ 1 ], { eggs: 2 } )
2、在逗号、分号、冒号之前(之后需要空格):
#符合约定的代码
if x == 4: print x, y; x, y = y, x
#不符合约定的代码
if x == 4 : print x , y ; x , y = y , x
3、在函数调用的参数列表的左括号前
#符合约定代码
spam(1)
#不符合约定的代码
spam (1)
4、在切片或索引的左方括号前
#符合约定的代码
dict[‘key‘] = list[index]
#不符合约定的代码
dict [‘key‘] = list [index]
在赋值(或其他)操作符两侧的多于一个的空格
#符合约定的代码
x = 1
y = 2
long_variable = 3
#不符合约定的代码
x = 1
y = 2
long_variable = 3
总是在下列二元操作符的两端使用单个空格,包括布尔操作符(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)
不建议使用复合语句(在一个物理行中存在多条语句)。
#符合建议的代码
if foo == ‘blah‘:
do_blah_thing()
do_one()
do_two()
do_three()
#不符合建议的代码
if foo == ‘blah‘: do_blah_thing()
do_one(); do_two(); do_three()
八、注释
1、注释应当为完整的句子,且句号结尾的句子后面应当有2个空格。如果注释很短,那么结尾的句号可以忽略。
2、短语注释或整句注释都应当以大写字母开头,除非该注释以首字母小写的标示符开头。
3、块注释应当和代码缩进保持一致。每行注释开头应以#开头,然后紧跟一个空格。
4、行注释至少和语句间隔2个空格。同样的,注释应当以#开头,然后紧跟一个空格。尽量少的使用行内注释。
九、文档字符串
1、对于所有的公有模块、类、函数和方法都需要编写文档字符串。
2、以"""开始,在同一行写文档字符串。如果有多行,则"""单独放在最后一行作为结尾。如果只有一行的文档字符串来说,将结尾的 """ 放在同一行也是可以的。
十、版本薄记
如果需要记录svn等版本,即在你的代码中需要有版本变更标记,请像这样书写。
__version__ = "$Revision: 70b79ccd671a $"
十一、命名规范
在Python里面,有一些具有特定意义的下划线前缀或者后缀的特殊格式。如:
1、单下划线开始---弱"内部使用"指示器。例如:from M import * 不会导入以下划线开始的对象。
2、单下划线结束---规定使用其来避免与Python关键字冲突,例如:
Tkinter.Toplevel(master, class_='ClassName') 在参数class后面加单下划线,避免与关键字class冲突
3、双下划线开始---命名一个类的属性时,调用"name mangling"(类FooBar中,__boo 变为了 _FooBar__boo; 见下文)
4、双下划线开始和结束---存活在用户控制命名空间的"magic"对象或属性。 例如__init__, __import__ 或 __file__。永远不要自定义这样的名字。
避免使用的命名
不要使用小写的L、大写的O、以及大写的I作为单字符变量名。容易与数字混淆
包与模块名称
1、模块应当使用简短、全小写的名字,也可使用下划线连接来提高可读性。
2、包也应当使用简短、全小写的名字,但不要使用下划线。
3、这是由于模块名与文件名关联,而在某些文件系统中大小写不敏感,且会截断过长的名字。
4、当使用C/C++来编写一个扩展模块时,应当使用下划线作为模块名的前缀。
类名
类名应当使用驼峰式,每一个单字的首字母都采用大写字母,例如:FirstName。内部使用的类名应当加下划线前缀。
异常名
异常也是一个类,所以需要遵循类名规则。但如果你的异常确实是个错误的话,请使用Error后缀。
函数名、方法名和数据成员名
1、函数名全小写,可以使用下划线分隔来提高可读性。
2、全局变量名遵循函数规则,而且最好是供本模块使用,可以使用__all__或者以单下划线开头来防止全局变量被from M import * 导入。
方法名与数据成员也遵循函数规则
1、当函数的参数名与保留字冲突时,使用下划线后缀(第二次提醒)。
2、在私有方法和私有数据成员前用单下划线前缀。
3、使用双下划线前缀来调用"name mangling"来避免与子类命名冲突。如果类Foo有个属性叫__a,那么它不能使用Foo.__a读取,但仍然可以Foo._Foo__a来读取。
4、常量通常在模块级别定义,使用全大写和下划线分隔的形式。
继承设计
1、当公有属性与保留字冲突时,在名称后面加下划线后缀(第三次提醒)。
2、对于简单的公有属性,最好直接访问其属性名,而非get/set方法。
十二、编程建议
1、代码应当适用于Python的多个实现。比如不要依赖CPython的高效字符串语句 a+=b,而应当使用"".join(),从而保证在不同实现上的线性开销。
2、当与类似于None的单例进行比较式,要使用is 或者 is not(不要使用not...is), 而不是使用等于操作。
3、当使用复杂比较实现排序操作时,最好实现全部的六个比较操作( __eq__ , __ne__ , __lt__ , __le__ , __gt__ , __ge__ )
4、从Exception继承不要从BaseException继承
5、当抛出一个异常的时候,使用raise ValueError('message')代替旧的raise ValueError, 'message'格式。这是由于当异常的参数很长或者是格式化字符串的时候,由于括号的关系,我们不需要使用多行连接符。 旧的格式在Python 3 中被移除。
6、当捕获一个异常的时候,要用详细的异常声明来代替简单的except: 语句。一个空的except:语句将会捕获 SystemExit 和 KeyboardInterrrupt 异常。这会使得很难用Control-C来中断一个程序,并且还会隐藏其他的问题。
7、另外,对于所有的try/except语句,限制try语句来减少必要代码的数量。 再者,可以避免掩盖问题。
8、使用with管理器或者try...finally对本地资源进行关闭和释放
9、使用str自己的方法,不要使用string模块的方法,string模块的效率比较低
10、使用''.startswith() 和 ''.endswith()而非字符切片去检测前缀或后缀。
Yes: if foo.startswith('bar'):
11、对象类型比较总要用 isinstance() 而非直接比较。
Yes: if isinstance(obj, int):
No: if type(obj) is type(1):
12、对于序列,(strings, lists, tuples),利用空序列为false这一点来进行判断,而非使用长度来判断。
Yes: if not seq:
if seq:
No: if len(seq)
13、别用‘==’进行布尔值和 True 或者 False 的比较。
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True: