Python编码规范
本文提供的 Python 编码规范基于 Python 主要发行版本的标准库。Python 编码规范的指导原则主要用于提升代码的可读性,使得在大量的 Python 代码中保持一致。许多项目有自己的编码规范,在出现规范冲突时,项目自身的规范优先。
Python 编码规范最常使用的是 PEP8 编码规范。
PEP8 编码规范中文版 PDF 下载地址:https://pan.baidu.com/s/1ZhrIODN1h1ccdXcPHbuDVQ
百度网盘提取码:o8oe
1. 命名
- 文件名
- 包
- 模块
- 类
- 函数和方法
- 函数和方法的参数
- 全局变量
- 变量
- 常量
- 异常 以“Error”作为后缀。
- 前导后缀下划线
全部小写,可使用下划线。
使用简短的小写的名字,如果下划线可以改善可读性可以加入,例如:mypackage。
使用简短的小写的名字,如果下划线可以改善可读性可以加入,例如:如mymodule。
总是使用首字母大写单词串。如MyClass。内部类可以使用额外的前导下划线。
函数名应该为小写,可以用下划线风格单词以增加可读性。如:myfunction,my_example_function。
总使用“self”作为范例方法的第一个参数。总使用“cls”作为类方法的第一个参数。
如果一个函数的参数名称和保留的关键字冲突,通常使用一个后缀下划线好于使用缩写或奇怪的拼写。
对于from M import *导入语句,如果想阻止导入模块内的全局变量可以使用旧有的规范,在全局变量上加一个前导的下划线。
*注意*:应避免使用全局变量
变量名全部小写,由下划线连接各个单词。如color = WHITE,this_is_a_variable = 1。
*注意*:
1.不论是类成员变量还是全局变量,均不使用 m 或 g 前缀。
2.私有类成员使用单一下划线前缀标识,多定义公开成员,少定义私有成员。
3.变量名不应带有类型信息,因为Python是动态类型语言。如 iValue、names_list、dict_obj 等都是不好的命名。
常量名所有字母大写,由下划线连接各个单词。例如:MAX_OVERFLOW、TOTAL。
1.一个前导下划线:表示变量或者方法非公有。
2.一个后缀下划线:避免关键字冲突。
3.两个前导下划线:当命名一个类属性引起名称冲突时使用。
4.两个前导和后缀下划线:内部有特殊用途的对象或者属性,例如__init__或者__file__。绝对不要创造这样的名字,而只是使用它们。
2. 缩进
使用4个空格来缩进代码,不要使用tab,也不要混用tab和空格。
对于行连接的情况, 你应该要么垂直对齐换行的元素,或者使用4空格的悬挂式缩进(这时第一行不应该有参数):
正确: # 与起始变量对齐 foo = long_function_name(var_one, var_two, var_three, var_four) # 字典中与起始值对齐 foo = { long_dictionary_key: value1 + value2, ... } # 4 个空格缩进,第一行不需要 foo = long_function_name( var_one, var_two, var_three, var_four) # 字典中 4 个空格缩进 foo = { long_dictionary_key: long_dictionary_value, ... }
3. 分号
不要在行尾加分号, 也不要用分号将两条命令放在同一行。
4. 行长度
- 每行不超过80个字符,其中长的导入模块语句和注释里的URL除外
- 不要使用反斜杠连接行。Python会将圆括号, 中括号和花括号中的行隐式的连接起来
正确: foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0)
x = ('这是一个非常长非常长非常长非常长 ' '非常长非常长非常长非常长非常长非常长的字符串')
# See details at # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_specification.html
5. 括号
宁缺毋滥的使用括号,除非是用于实现行连接, 否则不要在返回语句或条件语句中使用括号,不过在元组两边使用括号是可以的。
正确: 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)
6. 空行
顶级定义之间空2行,比如函数或者类定义。方法定义之间空1行。
方法定义、类定义与第一个方法之间,都应该空1行。函数或方法中,某些地方觉得合适就空一行。
7. 空格
- 按照标准的排版规范来使用标点两边的空格,括号内不要有空格,按照标准的排版规范来使用标点两边的空格
正确: spam(ham[1], {eggs: 2}, []) 错误: spam( ham[ 1 ], { eggs: 2 }, [ ] )
正确: if x == 4: print x, y x, y = y, x 错误: if x == 4 : print x , y x , y = y , x
正确: spam(1) 错误: spam (1) 正确: dict['key'] = list[index] 错误: dict ['key'] = list [index]
正确: x == 1 错误: x<1
正确: def complex(real, imag=0.0): return magic(r=real, i=imag) 错误: def complex(real, imag = 0.0): return magic(r = real, i = imag)
正确: foo = 1000 # 注释 long_name = 2 # 注释不需要对齐 dictionary = { "foo": 1, "long_name": 2, } 错误: foo = 1000 # 注释 long_name = 2 # 注释不需要对齐 dictionary = { "foo" : 1, "long_name": 2, }
8. 注释
- 文档字符串
- 函数和方法:
Python有一种注释方式: 使用文档字符串。文档字符串是包、模块、类或函数里的第一个语句。这些字符串可以通过对象的__doc__成员被自动提取,并且被pydoc所用。
对文档字符串的惯例是使用三重双引号"""。
每节应该以一个标题行开始,标题行以冒号结尾。除标题行外, 节的其他内容应被缩进2个空格。
列出每个参数的名字,并在名字后使用一个冒号和一个空格,分隔对该参数的描述.如果描述太长超过了单行80字符,使用2或者4个空格的悬挂缩进(与文件其他部分保持一致)。描述应该包括所需的类型和含义。如果一个函数接受foo(可变长度参数列表)或者**bar (任意关键字参数), 应该详细列出foo和**bar。
Returns: (或者 Yields: 用于生成器)
描述返回值的类型和语义。 如果函数返回None, 这一部分可以省略。
Raises:
列出与接口有关的所有异常。
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None): """Fetches rows from a Bigtable. Retrieves rows pertaining to the given keys from the Table instance represented by big_table. Silly things may happen if other_silly_variable is not None. Args: big_table: An open Bigtable Table instance. keys: A sequence of strings representing the key of each table row to fetch. other_silly_variable: Another optional variable, that has a much longer name than the other args, and which does nothing. Returns: A dict mapping keys to the corresponding table row data fetched. Each row is represented as a tuple of strings. For example: {'Serak': ('Rigel VII', 'Preparer'), 'Zim': ('Irk', 'Invader'), 'Lrrr': ('Omicron Persei 8', 'Emperor')} If a key from the keys argument is missing from the dictionary, then that row was not found in the table. Raises: IOError: An error occurred accessing the bigtable.Table object. """ pass
类应该在其定义下有一个用于描述该类的文档字符串。如果你的类有公共属性(Attributes),那么文档中应该有一个属性(Attributes)段,并且应该遵守和函数参数相同的格式。
class SampleClass(object): """ Summary of class here. Longer class information.... Longer class information.... Attributes: likes_spam: A boolean indicating if we like SPAM or not. eggs: An integer count of the eggs we have laid. """ def __init__(self, likes_spam=False): """Inits SampleClass with blah.""" self.likes_spam = likes_spam self.eggs = 0 def public_method(self): """Performs operation blah."""
最需要写注释的是代码中那些技巧性的部分。如果你在下次 代码审查 的时候必须解释一下,那么你应该现在就给它写注释。对于复杂的操作,应该在其操作开始前写上若干行注释。对于不是一目了然的代码,应在其行尾添加注释。为了提高可读性,注释应该至少离开代码2个空格。
# We use a weighted dictionary search to find out where i is in # the array. We extrapolate position based on the largest num # in the array and the array size and then do binary search to # get the exact number. if i & (i-1) == 0: # true iff i is a power of 2
9. 类 class
如果一个类不继承自其它类,就显式的从object继承,嵌套类也一样。
class SampleClass(object): pass class OuterClass(object): class InnerClass(object): pass class ChildClass(ParentClass): """Explicitly inherits from another class already."""
继承自 object 是为了使属性正常工作,并且这样可以保护你的代码,使其不受Python 3000的一个特殊的潜在不兼容性影响。这样做也定义了一些特殊的方法(魔法方法),这些方法实现了对象的默认语义,包括 new, init, delattr, getattribute, setattr, hash, repr, and str。
10. 导入 import
每个导入应该独占一行
正确: import os import sys 错误: import os, sys
导入总应该放在文件顶部,位于模块注释和文档字符串之后,模块全局变量和常量之前。
导入应该按照从最通用到最不通用的顺序分组:
- 标准库导入
- 第三方库导入
- 应用程序指定导入
每种分组都应该根据每个模块的完整包路径按字典序排序,忽略大小写。
import foo from foo import bar from foo.bar import baz from foo.bar import Quux from Foob import ar
11. 语句
通常每个语句应该独占一行。不过,如果测试结果与测试语句在一行放得下,也可以将它们放在同一行。
如果是if语句,只有在没有else时才能这样做。 特别地,绝不要对 try/except 这样做, 因为try和except不能放在同一行。
正确: if foo: bar(foo) 错误: if foo: bar(foo) else: baz(foo) try: bar(foo) except ValueError: baz(foo)
下一章:阿里数据库规范
阿里 MySQL 数据库规范:一、建表规约 1.【强制】表达是与否概念的字段,必须使用 is_xxx的方式命名,数据类型是 unsigned tinyint( 1表示是,0表示否)。2.【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。