您的位置:首页 > 编程语言 > Python开发

Python编码规范小结

2018-08-13 23:48 337 查看

一个良好的代码规范,往往能让工作事半功倍。

INF-qa Python 编码规范,可能有一些不适用,但是具有参考意义。

目录

1.介绍

1.1 开发背景

1.2 语言

1.3 版本

1.4 规范文档

2. 一致性的建议

3. 代码的布局

3.1 缩进

3.2 Tab 键还是空格

3.3 行的最大长度

3.4 空行

3.5 编码

4. 导入

5. 空格

5.1 其他建议

6. 注释

6.1 注释块

6.2 行内注释

7. 文档化

8. 版本注解

9. 命名约定

9.1 描述:命名风格

9.2 说明:命名约定

9.21 应避免的名字

9.2.2 模块名

9.2.3 类名

9.2.4 异常名

9.2.5 全局变量名

9.2.6 函数名

9.2.7 方法名和实例变量名

9.2.8 继承

10. 设计建议

11. Demo

12. The zen of python

1.介绍

1.1 开发背景

为了提高组内自动化开发效率,避免重复开发,对组内各模块已开发的自动化lib 库、

case 中常用的操作、以及其他工具的调用接口进行汇总,管理出 dsqa 组内自动化 case 开发的基础库。

1.2 语言

基础库采用 python 开发。需要调用的相关二进制工具的地方,为降低开发成本,暂采用直接调该工具,封出 python 方法接口。

1.3 版本

Python 版本较多,为避免上下版本的兼容性问题,开发采用统一版本。

Python 2.6.2/2.7.x

1.4 规范文档

为了方便维护、他人阅读使用,整理出该编码规范文档。请大家开发时遵循本规范进行更开发。

本文档参考自Guido 的《Python 风格指南》一文. 并从《Barry's style guide》中添加了部分内容,以及我的个人建议。

2. 一致性的建议

整个项目的开发中,请尽量保持一致性,尤其是一个模块或者一个函数中的一致性更为重要。

因此存在这样的一个问题:由于不同模块的 lib 库开发人不同,编码规范也可能不同, 整合起来会显得不够“和谐”。还是希望各模块lib 库负责人做相应的修改,尽量“和谐”。

3. 代码的布局

3.1 缩进

众所周知,python 是通过缩进来进行代码布局的。使用vi 可以在~/.vimrc 中配置几个空格来代表一个tab,从而来布局 python 函数的缩进。

3.2 Tab 键还是空格

Python 里有一句叫“以用空格为荣,以用 tab 键为耻”。但全用空格时确实很麻烦。因此,这里不限定用tab 键还是空格。但记住:不可混用!

你可以选择全部使用 tab 键,这样也不会出错。

3.3 行的最大长度

类似于函数中的行注释、函数体等,如果某一行很长,则导致换行折叠观看,很影响美

观,而且还不利于阅读。因此,对顺序排放的的大块文本(文档字符串或注释),推荐长度限制在 72 个字节内。

推荐使用反斜杠续行。

3.4 空行

用两行分割顶层函数和类的定义。用一行分割类成员方法的定义。

在一个函数内使用空行时请注意谨慎使用于一个逻辑段。

3.5 编码

在 python 2.4 之后内核已经开始支持 Unicode 了。无论什么情况下,使用 UTF-8 才是王道

[code] #-*- coding:utf-8 -*-

4. 导入

通常应该在单独行中使用导入。

例如:

[code]No: 	import sys, os
Yes:    import sys
import os

但是这样也是可以的:

[code]from types import StringType, ListType

imports 应该放在文件的顶部,仅在模块注释和文档字符串之后,在模块的全局变量和常量之前。

Imports 也是有顺序的:

    a.Python 标准库的 import;

    b.第三方库的 import;

    c.自定义的库的 import;

并且在每组的 import 之间使用一行空行分割。

5. 空格

以下地方不推荐出现空格:

a.紧挨着圆括号,方括号和花括号的

    如:"spam( ham[ 1 ], { eggs: 2 } )" 写成 "spam(ham[1], {eggs: 2})"

b.紧贴在逗号,分号或冒号前的

    如: "if x == 4 : print x , y ; x , y = y , x" 写成 "if x == 4: print x, y; x, y = y, x"

c.紧贴着函数调用的参数列表前开式括号的

    如: "dict ['key'] = list [index]" 写成 "dict['key'] = list[index]"

d.紧贴在索引或切片下标开始的开式括号前

    如: "dict ['key'] = list [index]" 写成 "dict['key'] = list[index]"

e.在赋值(或其它)运算符周围的用于和其它并排的一个以上的空格,如:

[code]x    =1
y    =2
long_variable    =3

写成

[code]x = 1
y = 2
long_variable = 3

5.1 其他建议

始终在这些二元运算符两边放置一个空格:赋值(=), 比较(==, <, >, !=, <>, <=,>=, in, not in, is, is

not), 布尔运算 (and, or, not)

按你的看法在算术运算符周围插入空格,始终保持二元运算符两边空格的一致。

一些例子:

[code]i = i+1
submitted = submitted + 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
c = (a + b) * (a - b)

不要在用于指定关键字参数或默认参数值的'='号周围使用空格,例如:

[code]1	def complex(real, imag=0.0):
2	    return magic(r=real, i=imag)

不要将多条语句写在同一行上

[code]No:    	if foo == 'blah': do_blah_thing()
Yes:    if foo == 'blah':
do_blah_thing()

No:	do_one(); do_two(); do_three()
Yes:	do_one()
do_two()
do_three()

6. 注释

注释必须跟代码保持一致,当你想修改代码时,建议优先修改注释。注释必须是完整的句子。

如果注释是一个句子或者短语,请首字母大写。如果注释很短,建议省略句末的句号。

注释块通常由一个或多个由完整句子构成的段落组成,每个句子应该以句号结尾。注释请使用英文。

约定使用统一的文档化注释格式有助于良好的习惯和团队的进步。

6.1 注释块

注释块通常应用于跟随着一些(或者全部)代码并和这些代码有着相同的缩进层次。注释块中每行以'#'和一个空格开始(除非他是注释内的缩进文本)。

注释块内的段落以仅含单个'#'的行分割。

注释块上下方最好有一空行包围(或上方两行下方一行,对一个新函数定义段的注释)。

6.2 行内注释

行内注释应该至少用两个空格和语句分开. 它们应该以'#'和单个空格开始

[code]x = x+1	 # Increment x

如果语意是很明了的,那么行内注释是不必要的,事实上是应该被去掉的. 不要这样写:

[code]x = x+1	        # Increment x
[code]x = x+1	 # Compensate for border

但是有时,这样是有益的:

[code]x = x+1  # Compensate for border

7. 文档化

为配合 pydoc;epydoc,Doxygen 等等文档化工具的使用,应该一直遵守编写好的文档字符串的约定。

多行文档字符串结尾的""" 应该单独成行,例如:

[code]"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""

对单行的文档字符串,结尾的"""在同一行也可以。

8. 版本注解

[code] versio____= "$Revision: 1.0.0.0 $"

这个行应该包含在模块的文档字符串之后,所有代码之前,上下用一个空行分割。

当然也可以这样:

[code]'''
@version:  1.0.0.0
'''

跟其他相关信息(如 author、copyright、date 等)一起。

9. 命名约定

现有的库的命名约定想必比较混乱,但对于今后即将开发的新的模块应尽量遵循该约定开发。对于已有的模块存在不同风格的,保证内部的一致性是首选的。

9.1 描述:命名风格

一般的命名风格大家都清楚。这里说几个特殊的注意点:

    a.单下划线作为前导,如:_single_begin,这是弱的内部使用标识,例如使用“from M import

*”的时候不会被导入;

    b.单下划线作为结尾的,如:single_end_,这一般用于跟 python 关键词冲突;

    c.双下划线前导,如: double_begin,类私有名;

    d.双下划线前导+结尾,如: double_begin_and_end  ,特殊对象或属性,存在于用户控制的命名空间中,如:  init  ,  import   等。有时可以被用户定义,用于触发某个特殊行为,如运算符重载。

9.2 说明:命名约定

9.21 应避免的名字

永远不要用:

    a.小写字母“l”(小写的“L”);

    b.大写字母“O”;

    c.大写字母“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 得到访问权。通常,双前导下划线应该只用来避免与类中的属性发生名字冲突。

9.2.8 继承

始终要确定一个类中的方法和实例变量是否要被公开。

同样,确定你的属性是否应为私有的。私有与非公有的区别在于:前者永远不会被用在一个派生类中,而后者可能会。

私有属性必须有两个前导下划线,无后置下划线。非公有属性必须有一个前导下划线, 无后置下划线。公共属性没有前导和后置下划线,除非它们与保留字冲突。

10. 设计建议

(1)与像  None  之类的单值进行比较的时候,应永远使用:‘is’或‘is not’:

    当你本意是"if x is not None"时,对写成"if x"要小心,因为例如当你测试一个默认为 None

的变量或参数是否被设置为其它值时,这个其它值可能是一个在布尔上下文中为假的值。

(2)基于类的异常总是好过基于字符串的异常:

    模块和包应该定义它们自己的域内特定的基异常类, 基类应该是内建的 Exception 类的子类。 还始终包含一个类的文档字符串。例如:

[code]1	class MessageError(Exception):
2	"""Base class for errors in the email package."""

(3)使用字符串方法代替字符串模块:

因为字符串方法总是非常的快。

(4)在检查前缀或后缀时避免对字符串进行切片:

用 startswith() 和endswith() 代替,因为它们是明确的并且错误更少。例如:

[code]No:	if foo[:3] == 'bar':
Yes:	if foo.startswith('bar'):

(5)对象类型的比较应该始终用 isinstance()代替直接比较类型:

[code]No:	if type(obj) is type(1):
Yes:	if isinstance(obj, int):

(6)检查一个对象是否是字符串时,紧记它也可能是 unicode 字符串。

(7)对序列,(字符串、列表、元组),使用空列表是 false 这个事实,因此"if not seq"或"if seq"

比 "if len(seq)"或"if not len(seq)"好。

(8)书写字符串文字时不要依赖于有意义的后置空格,这种后置空格在视觉上是不可辨别的。

(9)No                                                        Chinese! 包 括 注 释 , 也 请 尽 量 使 用 英 文 。

(10)自动化 case 中请使用 python logging 模块设定日志级别打印日志,而不要大量使

用 print 输出。

(11)Print 时请使用”%d””%s”等标准输出格式,请勿 str 和变量混合连接使用。

11. Demo

[code]#!/usr/bin/env python
# -*- coding:utf-8 -*-

__version =          "1.0.0.0"
__author =           "cuijingjing"
__date =             "Thu Nov 18 14:52:47 CST 2010"
__copyright =        "Baidu"

import sys
import os
import shutil
import stat

class Opfile:
def  inin  (self):
pass
def replace_file(self, file_name, replace_from, replace_to):
'''
@note: replace some string in a file, link 'sed'
@parameter file_name: the file you want to deal with
@parameter replace_from: string you want to replace
@parameter replace_to: the string you want to replace to
'''
if not os.path.exists(file_name):
print "File not exists
exit()

file_name = os.path.abspath(file_name)

ori_file = open(file_name,'r').read()
if ori_file.find(replace_from) != -1:
if shutil.copyfile(file_name, file_name + ".bak") !=
# backup first
replace_in = open(file_name + ".bak", 'r')
replace_out = open(file_name, 'w')
s = replace_in.read()

replace_out.write(s.replace(replace_from, replace_to))
else:
print "[ERROR] not find \"" + replace_from + "\" in \"" + file_name + "\""
exit()

if    name 	== " main ":
op_file = Opfile()
op_file.replace_file("/home/cuijingjing/dgl/bin/test/test.c", "cuijingjing", "nnrand48")

这里我写的 demo,也不一定完全百分百地跟规范一模一样,但至少能确保他人阅读起来不会费劲。

用 epydoc 生成文档后,epydoc 会识别出你的注释信息,并在 moudle 中体现出来,如下图:

对于类方法,它的参数(Parameters)是什么,它是用来干什么的(Note)都一目了然。

12. The zen of python

最后附上《The zen of python》,希望我们的开发越来越规范,整个团队进步越来越快!

The Zen of Python

by Tim Peters

 

Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex.

Complex is better than complicated. Flat is better than nested.

Sparse is better than dense. Readability counts.

Special cases aren't special enough to break the rules. Although practicality beats purity.

Errors should never pass silently. Unless explicitly silenced.

In the face of ambiguity, refuse the temptation to guess.

There should be one-- and preferably only one --obvious way to do it.

Although that way may not be obvious at first unless you're Dutch.

Now is better than never.

Although never is often better than *right* now.

If the implementation is hard to explain, it's a bad idea.

If the implementation is easy to explain, it may be a good idea.

Namespaces are one honking great idea -- let's do more of those!

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: