Google Python 编码规范指南
这是 Google 为其内部 Python 代码制定的编码规范和风格指南,目的是帮助开发者编写干净、一致且可维护的 Python 代码。英文完整版可以访问 Google Style Guide。
语言规则
Lint 工具
使用pylint等工具对代码进行检查可以帮助发现常见的错误和问题。
导入格式
导入语句应该遵循以下规则:
- 每个导入应该独占一行。
推荐格式:
import os
import sys不推荐格式
import os, sys-
导入应该放在文件顶部,位于模块注释和文档字符串之后,模块全局变量和常量之前。
-
导入应该按照从最通用到最不通用的顺序分组:
- 标准库导入
- 第三方库导入
- 应用程序特定导入
future 语句
__future__ 导入允许在当前 Python 版本中使用更现代的语法特性。即使当前不使用这些特性,保留这些导入可以防止后续修改代码时无意中依赖于旧行为,例如:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function风格规则
分号
不要在行尾加分号,也不要用分号将两条命令放在同一行。
行长度
每行不超过80个字符,以下情况除外:
- 长的导入模块语句
- 注释里的URL
在编写Python代码时,应避免使用反斜杠来连接行。我们可以利用Python的特性,即圆括号、中括号和花括号会隐式地连接其中的行。
以下是推荐的使用方式示例:
foo_bar(self, width, height, color='black', design=None,
x='foo', emphasis=None, highlight=0)
if (width == 0 and height == 0 and
color == 'red' and emphasis == 'strong'):对于长字符串,可以使用圆括号实现隐式行连接,例如:
x = ('这是一个非常长非常长非常长非常长'
'非常长非常长非常长非常长非常长非常长的字符串')括号
宁缺毋滥地使用括号。除非是用于实现行连接,否则不要在返回语句或条件语句中使用括号,但在元组两边使用括号是可以的。
推荐使用方式:
if foo:
bar()
while x:
x = bar()
if x and y:
bar()
if not x:
bar()
return foo
for (x, y) in dict.items(): ...不推荐使用方式;
if (x):
bar()
if not(x):
bar()
return (foo)缩进
用 4 个空格来缩进代码,绝对不要用 tab ,也不要 tab 和空格混用。
文件和sockets
在文件和 sockets 结束时,显式地关闭它们。推荐使用 "with" 语句来管理文件,例如:
with open("hello.txt") as hello_file:
for line in hello_file:
print(line)对于不支持使用 "with" 语句的类似文件的对象,使用contextlib.closing() ,例如:
import contextlib
with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page:
for line in front_page:
print(line)字符串
字符串格式化
避免在循环中用 + 和 += 操作符来累加字符串。
推荐使用 .join() 方法连接字符串列表,例如:
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)不推荐的使用方式:
employee_table = '<table>'
for last_name, first_name in employee_list:
employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name)
employee_table += '</table>'字符串引号
在同一个文件中,保持使用字符串引号的一致性。使用单引号 ' 或者双引号 " 之一来引用字符串,并在同一文件中沿用。
为多行字符串使用三重双引号 """ 而非三重单引号 ''' 。文档字符串必须使用三重双引号 """ 。
推荐使用方式:
print("This is much nicer.\n"
"Do it this way.\n")不推荐使用方式:
print("""This is pretty ugly. Don't do this.""")注释
文档字符串
Python 有一种独特的注释方式:使用文档字符串。文档字符串是包、模块、类或函数里的第一个语句,可以通过对象的 __doc__ 成员被自动提取。
文档字符串应该这样组织:
- 首先是一行以句号、问号或惊叹号结尾的概述
- 接着是一个空行
- 接着是文档字符串剩下的部分
函数和方法的文档字符串
文档字符串应该包含函数做什么,以及输入和输出的详细描述。关于函数的几个方面应该在特定的小节中进行描述,例如:
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
"""取回表格中的行
获取表格中对应于键值的行数据。
Args:
big_table: 一个表格对象
keys: 需要获取的行的键值列表
other_silly_variable: 另一个参数
Returns:
一个字典映射键值到行数据
Raises:
IOError: 访问表格对象时发生错误
"""
pass类的文档字符串
类应该在其定义下有一个用于描述该类的文档字符串。如果有公共属性,文档中应该有一个属性段,例如:
class SampleClass(object):
"""类的摘要
详细的类信息...
Attributes:
likes_spam: 布尔值,指示我们是否喜欢SPAM
eggs: 整数,表示我们已下的蛋的数量
"""
def __init__(self, likes_spam=False):
"""初始化SampleClass"""
self.likes_spam = likes_spam
self.eggs = 0
def public_method(self):
"""执行操作"""
pass块注释和行注释
最需要写注释的是代码中那些技巧性的部分。对于复杂的操作,应该在其操作开始前写上若干行注释;对于不是一目了然的代码,应在其行尾添加注释。
TODO 注释
为临时代码使用 TODO 注释,这是一种短期解决方案。TODO 注释格式如下:
# TODO(kl@gmail.com): 在这里使用"*"进行字符串重复
# TODO(Zeke): 改为使用关系如果 TODO 是 "将来做某事" 的形式,请确保包含一个指定的日期或事件。
命名规范
Python 之父 Guido 推荐的命名规范:
| 类型 | 公共 | 内部 |
|---|---|---|
| 模块 | lower_with_under | _lower_with_under |
| 包 | lower_with_under | |
| 类 | CapWords | _CapWords |
| 异常 | CapWords | |
| 函数 | lower_with_under() | _lower_with_under() |
| 全局/类常量 | CAPS_WITH_UNDER | _CAPS_WITH_UNDER |
| 全局/类变量 | lower_with_under | _lower_with_under |
| 实例变量 | lower_with_under | _lower_with_under (protected) 或 __lower_with_under (private) |
| 方法名 | lower_with_under() | _lower_with_under() (protected) 或 __lower_with_under() (private) |
避免使用的命名:
- 单字符名称,除了计数器和迭代器
- 包/模块名中的连字符()
- 双下划线开头并结尾的名称(Python保留,例如
__init__)
命名约定:
- "内部(Internal)"表示仅模块内可用,或者在类内是保护或私有的
- 用单下划线(_)开头表示模块变量或函数是 protected 的
- 用双下划线(__)开头的实例变量或方法表示类内私有
- 将相关的类和顶级函数放在同一个模块里
- 对类名使用大写字母开头的单词(如 CapWords,即 Pascal 风格),但是模块名应该用小写加下划线的方式(如 lower_with_under.py)