1.介绍
1.1.开发背景
为了提高组内自动化开发效率,避免重复开发,对组内个模块已开发的自动化 lib 库、case中常用的操作、以及其他工具的调用接口进行汇总,管理出 dsqa 组内自动化 case 开发的基础库。
1.2.语言
基础库采用python开发,需要调用的相关的二进制工具的地方,为降低开发版本,暂采用直接调该工具,封出python方法接口。
1.2.1.版本
因为python2和python3版本的不兼容性,所以我们一般使用python3
1.3.规范文档
为了方便维护、他人阅读使用,整理出该编码规范文档、请大家开发时遵循本规范进行开发。
本文档参考自Guido的《Python 风格指南》一文,并从《Barry‘s style guide》中添加了部分内容,以及我的个人建议。
2.一致性的建议
整个项目的开发中,请尽量保持一致性,尤其是一个模块或者一个函数中的一致性更为重要。
因此存在这样的一个问题:由于不同模块的 lib 库开发人不同,编码规范也可能不同,整合起来会显得不够 “和谐” 。还是希望各模块 lib 库负责人做相应的修改,尽量 “和谐”。
3.代码的布局
3.1.缩进
众所周知,python是通过缩进来进行代码布局的,使用 vi 可以在~/ .vimrc 中配置几个空格来代表一个tab,从而来布局 python 函数的缩进。
3.2Tab键还是空格
Python 里有一句话叫“以用空格为荣,以用tab键为耻”。但全用空格时确实很麻烦。因此,这里不限定用 tab 键还是空格。但记住:不可混用!
你可以选择全部使用tab键,这样也不会报错。
3.3行的最大长度
类似于函数中的行注释、函数体等,如果某一行很长,则导致换行折叠观看,很影响美观,而且还不利于阅读。因此,对顺序排放的大块文本(文档字符串或注释),推荐长度限制72个字节内。
推荐使用反斜杠续行。
3.4.空行
用两行分割顶层函数和类的定义。
用一行分割类成员方法的定义。
在一个函数内使用空格时请注意谨慎使用于一个逻辑段。
3.5.编码
在python 2.4 之后内核已经开始支持 Unicode了。
无论什么情况下,使用Utf-8才是王道!
#两种编写编码的格式:
# -*-coding:utf-8-*-
# -cpding=utf-8
4.导入
通常应该在单独行中使用
例如:
No: import sys,os
Yes: import sys
import os
但是这样也是可以的:
from types import StringType,ListType
import应该放在文件的顶部,仅在模块注释和文档字符串之后,在模块的全局变量和常量之前。
Import 也是有顺序的:
-
Python 标准库的 import;
-
第三方库的 import;
-
自定义的库的 import;
并且在每组的 import 之间使用一行空格分割。
5.空格
以下地方不推荐使用空格:
1)紧贴着圆括号,方括号和花括号的
如:“span(ham[1],{eggs:2})”.写成"spam(ham[1],{eggs:2})"
2)紧贴着在逗号,分号,冒号前的
如:"if x == 4 : print x,y ; x = y , x".写成 "if x == 4 : print x , y; x , y = y , x".
3)紧贴着函数调用的参数列表前开式括号的
如:“dict['key'] = list [index]”. 写成 "dict['key'] = list[index]".
4)紧贴在索引或切片下标开始的开式括号前
如:"dict['key'] = list[index]",写成"dict['key'] = list[index]".
5)在赋值(或其他)运算符周围的用于和其他并排的一个以上的空格,如:
如: x =1
y =2
log =3
改成:1 x = 1
2 y = 2
3 log = 3
5.1.其它建议
始终在这些二元运算符两边放置一个空格:赋值(=),比较(==,<,>,!=,<>,<=,>=,in,not in ,is,is not),布尔运算 (and,or,not).
按你的看法在算术运算周围插入空格. 始终保持二元运算两边空格的一致.
i = i + 1
b = b + 1
x = x*2-1
不要在用于指定关键字参数或默认参数值的’=’ 号周围使用空格,例如:
1 def complex(real,image=0.0):
2 return magin(r=real,i=imag)
不要将多条语句写在同一行上.
No: if foo == 'blah': do_blah_thing()
Yes: if foo == 'blan':
do_blan_thing()
No: do_one();do_two();do_three()
Yes: do_one()
do_two()
do_three()
6.注释
建议:
注释必须跟代码保持一致,当你想修改代码时,建议优先修改注释。
注释必须是一个完整的句子。
如果注释是一个句子或者短语,请首字母大写。
如果注释很短,建议省略句末的句号。
注释块通常有一个或多个由完整句子构成的段落组成每个句子应该以句号结尾。
注释请使用英文。
约定使用统一的文档化注释格式有助于良好的习惯和团队的进步。
6.1注释块
注释块通常应用于跟随着一些(或者全部)代码并和这些代码有着相同的缩进层次。、
注释块中每行以’#'和一个空格开始(除非他是注释内的缩进文本)。
注释块内的段落以仅含单个’#'的行分割。
注释块上下方最好有一空行包围(或上方两行下方一行,对一个新函数定义段的注释)。
6.2行内注释
行内注释应该至少用两个空格和语句分开,他们应该以’#'和单个空格开始。
x = x+1 # Increment x
如果语意识很明了的,那么行内注释是不必要的,事实上是应该被去掉的,不要这样写:
x=x+1 # increment x
8.版本注解
1 __version__="$Revision:1.0.0.0$"
这个行应该含在模块的文档字符串之后,所有代码之前,上下用一个空行分割。
当然也可以这样:
1 ""
2 @version 1.0.0.0
3 ""
9.命名约定
现在库的命名约定想必比较混乱,但对于今后即将开发的新的模块应尽量遵循该约定开发。对于已有的模块存在不同风格的,保证内部的一致性是首选的。
9.1.描述:命名风格
一般的命名风格大家都清楚。这里说几个特殊的注意点:
1)单下划线作为前导,如:_single_begin,这是弱的内部使用标识,例如使用"from M import *"的时候不会被导入;
2)单下划线作为结尾的,如:single_end_,这一般用于跟 python 关键词冲突;
3)双下划线前导,如:__double_begin,类私有名;
4)双下划线前导+结尾,如:double_begin_and_end,特殊对象或属性,存在于用户控制的命名空间中,如:int,__import__等。有时可以被用户定义,用于触发某个特殊行为,如运算符重载。
9.2.1.应避免的名字
永远不要用
1)小写字母“l”(小写的"L");
2)大写字母“O”;
3)大写字母“I”(读音 eye);
作为单字符的变量名,因为不利于跟数字“0”和”1“很好的区分开来。
当要用小写字母“l”时,请用大写字母“L”代替。
9.2.2.模块名
模块应该是不含下划线的,简短的,小写的名字。
因为模块名被映射到文件名,有些文件系统大写不敏感并且截短长名字,模块名被选为相当短是重要的—这在 Unix 上不是问题,但当代码传到 Mac 或 Windows 上就可能是个问题了。
9.2.3.类名
几乎没有例外,类名总是使用首字母大写、驼峰命名单词串的约定。
9.2.4.异常名
首字母大写、驼峰命名
9.2.5.全局变量名
这个的约定跟用于函数的约定差不多。
那些模块,应该在那些不想被导入的全局变量(还有内部函数和类)前加一个下划线。
9.2.6函数名
函数名应该为小写、动宾短语,可能用下划线风格单词以增加可读性。如:open_file()
9.2.7.方法名和实例变量名
小写、动宾短语、下划线风格以增加可读性。
但前导下划线仅用于不打算作为类的公共接口的内部方法。
双前导下划线表示类私有的名字, python 将这些名字和类名连接在一起。
如果类 Foo 有一个属性名为 __a,它不能以 Foo.__a 访问,如果你非要访问,还是可以通过 Foo.__Foo__a得到访问权。通常,双前导下划线应该只用来避免与类中的属性发生名字冲突。
10.设计建议
1)与像 None 之类的单值进行比较的时候,应永远使用:’is‘ 或 ’is not’:
当你本意是"if x is not None"时,对写成“if x”要小心,因为例如当你测试一个默认为None的变量或参数是否被设置为其它值时,这个其它值可能是一个在布尔上下文中为假的值。
2)基于类的异常总是好过基于字符串的异常:
模块和包应该定义它们自己的域内特定的基异常类,基类应该是内建的Exception 类的子类,还始终包含一个类的文档字符串。例如:
1 class MessageError(Exception)
2 """Base class for errors in the email package."""
3)使用字符串方法代替字符串模块:
因为字符串方法总是非常的快。
4)在检查前缀或后缀时避免对字符串进行切片:
用startswith() 和 endswith() 代替,因为它们是明确的并且错误更少
No: if foo[:3]=='bar':
Yes: if foo.startswith('bar')
5)对象类型的比较应该始终用 isinstance() 代替直接比较类型:
例如:
No:if type(obj) is type(1):
Yes: if isinstance(obj,int):