曲岳 QuYue
前言
代码本没有规范,但是用的人多了就有了规范。 其实在许多程序员的努力下,发现了许许多多可以让代码更加规则的规范。
做为一个程序员,肯定免不了要阅读别人的代码。众所周知,有的代码无论在可读性上还是外观上都十分好看,而有的代码杂乱无章让人读起来十分痛苦。遵守代码规范就是一种可以改良代码可读性的重要方法。有人曾总结代码开发的重要性 :
规范的代码可以促进团队合作
规范的代码可以减少bug处理
规范的代码可以降低维护成本
规范的代码有助于代码审查
养成代码规范的习惯,有助于程序员自身的成长。
当然作为一门语言,Python也是有属于自己的规范的,而且本身Python就是一个和结构十分相关的语言例如:缩进,所以掌握好Python的代码规范就显得尤为重要。
1 基本规范
1.1 代码格式
1.1.1 缩进
统一使用4个空格来进行缩进。
绝对不要使用tab键来进行缩进,除非编译器中设置了tab=4个空格。
1.1.2 行宽
每行代码尽量不超过80个字符,在特殊情况下可以超过80,但最长不可以超过120.
理由如下:
这在查看side-by-side的diff时很有帮助。
方便在控制台下查看代码。
太长可能是设计有缺陷。
1.1.3 引号
通常,自然语言使用双引号,机器标示使用单引号,因此代码里多数应该使用单引号。
具体如下:
自然语言 使用双引号"..."
例如 错误信息u"Hello, world";很多情况是unicode,使用u"你好,世界"
机器标识 使用单引号'...'
例如 dict里的key
正则表达式 使用原生的双引号r"..."
**文档字符串(docstring)**使用三个双引号"......c"
1.1.4 空行
模块级函数和类定义之间空两行。
类成员函数之间空一行。
可以使用多个空行分隔多组相关的函数
函数内逻辑无关段落之间空一行。
其余地方尽量不要空行。
1 2 3 4 5 6 7 8 9 10 11 class A : def __init__ (self) : pass def hello (self) : pass def main () : pass
1.1.5 字符串
避免循环中用+和-操作符来累加字符串。由于字符串是不可变的,这样做会创建不必要的临时对象。通常的做法是,将每个字串加到一个列表里,在最后用.join连接列表。
1 2 3 4 5 items = ['<table>' ] for last_name, first_name in employee_list: items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name)) items.append('</table>' ) employee_table = '' .join(items)
1.2 导入格式
每个导入应该分行书写,但是导入同一个模块的多个类可以放在行中书写
1 2 3 4 5 6 7 import osimport sysfrom time import time, ctimeimport sys,os
1 2 3 4 5 from foo.bar import Barfrom ..bar import Bar
import语句应该放在文件头部,置于模块说明及docstring之后,于全局变量之前。同时,应保证从最通用到最不通用的顺序分组:
import语句应该按照顺序排列,每组之间用一个空行分隔
1 2 3 4 5 6 7 import osimport sysimport msgpackimport zmqimport foo
1 import myclass import MyClass
1 2 3 4 5 import barimport foo.barbar.Bar() foo.bar.Bar()
1.3 空格格式
1.3.1 二元操作符
在二元操作符两边各加一个空格,包括:赋值=,比较==,!=,<,>,<=,>=,in,not in,is,is not,布尔and,or,not
1 2 3 4 5 6 7 8 9 10 11 i = i + 1 submitted += 1 x = x * 2 - 1 h = x * x + y * y i=i+1 submitted +=1 x = x*2 - 1 h = x*x + y*y
但是不要在逗号,分号,冒号前面加空格,但应该在他们后面加(除了在行尾)
1 2 3 4 5 6 7 8 9 if x == 4 : print x, y x, y = y, x if x == 4 : print x , y x , y = y , x
当=用于指示关键字参数或默认参数值时,不要在其两测使用空格
1 2 3 4 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)
1.3.2 括号之间
1 2 3 4 5 spam(ham[1 ], {eggs: 2 }) spam( ham[1 ], {eggs : 2 } )
1 2 3 4 5 6 spam(1 ) dict['key' ] = list[index] spam (1 ) dict ['key' ] = list [index]
1.3.3 对齐
不要为对齐赋值语句或注释而使用额外的空格,增加维护的负担
1 2 3 4 5 6 7 8 9 x = 1 y = 2 long_variable = 3 x = 1 y = 2 long_variable = 3
1.4 换行格式
1 2 3 4 5 6 7 session.query(MyTable).\ filter_by(id=1 ).\ one() print('Hello, ' \ '%s %s' %\ ('Harry' ,'Potter' ))
不要使用复合语句一行中有多个语句
if/for/while等尽量换行
1.5 文档格式
1.5.1 文档编码
如果没有特殊情况,文件一律使用UTF-8 编码。
如果没有特殊情况,文件头部必须加入#-*-coding:utf-8-*-标识。
1.5.2 文档字符串 docstring
Python有一种独一无二的注释方式:docstring,更加详细的讲解将在2.2中讲。
所有的公共模块、函数、类、方法,都应该写docstring。私有方法不一定需要,但应该在def后提供一个块注释来说明
docstring的结束"""应该独占一行,除非只有一行
1 2 3 4 5 """Return a foobar Optional plotz says to frobnicate the bizbaz first. """ """Oneline docstring"""
1.6 main函数
即使是一个打算被用做脚本的文件,也应该是可导入的。并且简单的导入不应该让该脚本的主功能(main function)被执行。主功能应该放在main()函数中
在Python中通常使用如下方法:
1 2 3 4 5 def main () : ... if __name__ == '__main__' : main()
2 注释规范
2.1 代码注释
2.1.1 块注释
通常#号后空一格,段落间用空行分开(同样需要#号)
2.1.2 行注释
至少使用两个空格和语句分开,注意不要使用无意义的注释。
2.1.3 建议
在代码的关键部分(或负责的地方),能写注释的要尽量写注释
比较重要注释段,使用多个等号隔开,可是更加醒目,突出重要性。
1 2 3 4 5 6 7 8 9 10 app = create_app(name, options) if __name__ == '__main__' : app.run()
2.2 文档注释
文档注释一般在模块的头部、函数和类的头部,这样我们就可以通过调用对象的__doc__来获取文档。经过设置也可以在IDE和编辑器中得到Docstring的提示。
通常文档注释以"""开头和结尾,首行不换行,如有多行,末行必需单独换行。
下面是Google的docstring风格示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 """Example docstrings. This module demonstrates documentation as specified by the `Google Python Style Guide`_. Docstrings may extend over multiple lines. Sections are created with a section header and a colon followed by a block of indented text. Example: Examples can be given using either the ``Example`` or ``Examples`` sections. Sections support any reStructuredText formatting, including literal blocks:: $ python example_google.py Section breaks are created by resuming unindented text. Section breaks are also implicitly created anytime a new section starts. """
docstring一定要具体的描述其具体内容,解释具体的参数和返回值等
函数参数、返回值等的说明可以采用numpy的标准,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def func (arg1, arg2) : """在这里写函数的一句话总结(如: 计算平均值). 这里是具体描述. 参数 ---------- arg1 : int arg1的具体描述 arg2 : int arg2的具体描述 返回值 ------- int 返回值的具体描述 参看 -------- otherfunc : 其它关联函数等... 示例 -------- 示例使用doctest格式, 在`>>>`后的代码可以被文档测试工具作为测试用例自动运行 >>> a=[1,2,3] >>> print [x + 3 for x in a] [4, 5, 6] """
文档注释尽量不要中英文混用
模块、公有类、公有方法,能写文档注释的,应该尽量写文档注释
一个函数当满足以下条件就可以不需要文档字符串
外部不可见
非常短小
简单明了
3 命名规范
3.1 命名约定
所谓的“内部”表示仅模块内可用,或者,在类内或私有的。
用单下划线-开头表示模块变量或函数是protected的(使用import * from时不会包含)
用双下划线__开头的实例变量或方法表示类内私有
可以将相关的类和顶级函数放在同一个模块里
3.1 模块命名
通常模块尽量使用小写命名,尽量不要使用_(除非多个单词,且数量不多的情况)
1 2 3 4 5 6 import decoderimport html_parserimport Decoder
3.2 类命名
通常类名使用驼峰(CamelCase)命名风格,即每个单词的首字母大写,私有类需要用一个下划线(或两个下划线)开头
1 2 3 4 5 6 7 8 class Farm () : pass class AnimalFarm () : pass class _PrivateFarm () : pass
我们可以将相关的类和顶级函数放在同一个模块里,不用象Java一类一个模块
### 3.3 函数
通常函数名一律小写,如果有多个单词,使用下划线隔开
1 2 3 4 5 def hello () : print("Hello" ) def hello_world () : print("Hello, world" )
- 私有函数在函数前加一个下划线
1 2 3 4 class Person () : def _private_func () : pass
3.4 变量名
1 2 3 apple = 1 huawei = 2 xiaomi_10 = 3
3.5 常量
1 2 MAX_LOOP = 100 MAX_ERROR = 0.1
To my family,with love
To my friend,with encourage
To my teacher,with gratitude