Python代码规范

曲岳 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 os
import sys
from time import time, ctime

# 不推荐的写法
import sys,os
  • import语句应该使用明确的import
1
2
3
4
5
# 推荐的写法
from foo.bar import Bar

# 不推荐的写法
from ..bar import Bar
  • import语句应该放在文件头部,置于模块说明及docstring之后,于全局变量之前。同时,应保证从最通用到最不通用的顺序分组:
    • 标准库导入
    • 第三方库导入
    • 应用程序指定导入
  • import语句应该按照顺序排列,每组之间用一个空行分隔
1
2
3
4
5
6
7
import os
import sys

import msgpack
import zmq

import foo
  • 导入其他模块的类的定义时,可是使用相对导入
1
import myclass import MyClass
  • 如果发生命名冲突,则可以使用命名空间
1
2
3
4
5
import bar
import foo.bar

bar.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 # 1
y = 2 # 2
long_variable = 3 # 3

# 不推荐的写法
x = 1 # 1
y = 2 # 2
long_variable = 3 # 3

1.4 换行格式

  • Python是支持括号内的换行。这时有两种情况

    1. 第二行缩进到括号的起始处
    1
    2
    foo = function_name_1(var_1, var_2,
    var_3, var_4)
    1. 第二行缩进4个空格
    1
    2
    3
    foo = function_name_2(
    var_1, var_2,
    var_3, var_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 块注释
  • 通常#号后空一格,段落间用空行分开(同样需要#号)
1
2
3
4
5
# 块注释
# 块注释
#
# 块注释
# 块注释
2.1.2 行注释
  • 至少使用两个空格和语句分开,注意不要使用无意义的注释。
1
2
3
4
5
# 推荐的写法
x = x + 1 # 边框加粗一个像素

# 不推荐的写法
x = x + 1 # 无意义的注释
2.1.3 建议
  • 在代码的关键部分(或负责的地方),能写注释的要尽量写注释
  • 比较重要注释段,使用多个等号隔开,可是更加醒目,突出重要性。
1
2
3
4
5
6
7
8
9
10
app = create_app(name, options)


# =======================
# 制作app
# ========================


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]
"""
  • 文档注释尽量不要中英文混用
  • 模块、公有类、公有方法,能写文档注释的,应该尽量写文档注释
  • 一个函数当满足以下条件就可以不需要文档字符串
    1. 外部不可见
    2. 非常短小
    3. 简单明了

3 命名规范

3.1 命名约定

  • 所谓的“内部”表示仅模块内可用,或者,在类内或私有的。
  • 用单下划线-开头表示模块变量或函数是protected的(使用import * from时不会包含)
  • 用双下划线__开头的实例变量或方法表示类内私有
  • 可以将相关的类和顶级函数放在同一个模块里

3.1 模块命名

  • 通常模块尽量使用小写命名,尽量不要使用_(除非多个单词,且数量不多的情况)
1
2
3
4
5
6
# 正确的模块名
import decoder
import html_parser

# 不推荐的模块名
import 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

© 2018. | 由Hexo强力驱动 | 本人基于Huno主题进行改良