通用
排版规范
1、程序块要采用缩进风格编写。函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格。
- 例:
# 文件自检
file_check()
{
if [[ ! -n $file_01 ]];then
echo "TM_ota.sh 文件不存在。"
exit
elif [[ ! -n $file_02 ]];then
echo "TM_app.sh 文件不存在。"
exit
fi
}
函数内部统一缩进一格,判断语句内部统一缩进一格。
2、不要把多个短语写在一行中,即一行只写一条语句。
- 比如错误示范
a=1;b=2;c=$((a+b));
3、If、for、do、while、case、switch、default等语句自占一行。
4、程序块的分界符(如C++/C#语言中的‘{’和‘}’)应各自独占一行并且位于同一列,同时与引用它们的语句左对齐。
- 3、4 都可以参考第一个例子。
5、行长度,每行不超过80个字符。以下情况除外
- 长的导入模块语句
- 注释里的URL
shell
一、注释
1、脚本头部注释
脚本头部注释,主要是改脚本的描述信息,这些信息主要包括脚本的作者、开发时间、脚本的功能描述,如:
#!/bin/bash
#####################################
#Script: XXXX
#Author: XXXX
#Date: XX-XX-XX
#Description: XXXXXX
#Usage: XXXX
#####################################
其中,(根据项目实际需要,也可以添加其他描述信息)
2、其他注释
- 函数注释:描述函数的具体功能;放在函数上一行。
- 代码注释:对关键或复杂代码进行注释;注释放在代码上一行或代码后。
二、命名规范
1、变量名
- 命名只能使用英文字母,数字和下划线。
- 只有一个英文单词时使用全拼;有多个单词时,使用下划线分隔;长度较长时,可以取单词前3~4字母。
- 避免使用Linux的保留字如true、关键字如pwd等。
- 配置文件中定义的环境变量名统一大写。
2、函数命名
同变量命名
3、文件命名
- linux不以文件后缀来区分文件类型,但为了便于日常管理和维护,shell脚本习惯以.sh结尾。
- 文件名全部以小写命名,不要大小写混用(不推荐驼峰命名法,大小写混用在特殊情况下会存在问题)。
- 文件名尽可能做到“见名知意”;可以参考变量命名。
三、函数规范
1、函数结构
- 每一个小功能都封装到独立的函数类,一个函数只完成一个功能;在脚本尾部,通过函数的顺序调用将整个脚本逻辑串联起来。
- 控制函数的大小,函数体的行数尽量控制在100行左右;过大的函数要分割成两个或者多个函数。
2、函数复用
- 多次调用的功能要抽离出独立的函数,提高编码效率,降低维护成本。
- 对常用的功能(如计算日期,发邮件、写日志)的功能,封装成函数后形成独立的脚本,其他脚本引入即可。
四、编写规范
1、缩进
良好的缩进可以提高代码的可读性,建议代码中统一用制表符(一般4个字符)作为缩进。
2、分割长行
参考通用部分
3、分离符合体
主要是针对 if语句、while语句,参考通用部分
# 连续录像压力测试
test_case_02()
{
clear
echo "开始连续录像压力测试:"
while((1))
do
echo "Loop "$i
takevideo
sleep 2
echo "take video success ..."
sleep 1
echo " "
((i++))
done
}
4、变量统一管理
- shell脚本中使用的全局变量,要统一定义。一般在init()函数中进行统一初始化。
- 函数内部使用的变量,最好也在函数开始位置进行初始化。
- 函数内部局部变量用local修饰。
- 多个脚本都需要引用的变量,统一在配置文件中定义(后续会详细说明)。
- 变量引用,以 ${} 方式。
5、shell脚本结构
shell 脚本,自上而下一次为:
- set_env() 该函数用于初始化脚本的环境,引入全局变量。
- init() 该脚本用于初始化当前脚本的全局参数。
- xxx() 其他脚本,与具体业务相关。
- 依次调用自上而下的脚本,形成处理逻辑。
五、脚本复用
- 将常用功能封装成函数,把一类功能的函数写入一个脚本中,其他脚本在需要某一类功能时,直接引入该脚本,调用函数即可。
- 形成固定的脚本引用方式,如脚本开头固定引入某些脚本,达到设置脚本运行环境的功能。
Python
一、编写规范
1、分号
不要在行尾加分号, 也不要用分号将两条命令放在同一行
2、行长度
每行不超过80个字符
以下情况除外:
- 长的导入模块语句
- 注释里的URL
推荐:
foo_bar(self,width,height,color='black',design=None,x='foo',
emphasis=None,highlight=0)
if(width ==0andheight ==0and
color =='red'andemphasis =='strong'):
如果一个文本字符串在一行放不下, 可以使用圆括号来实现隐式行连接:
x =('这是一个非常长非常长非常长非常长'
'非常长非常长非常长非常长非常长非常长的字符串')
在注释中,如果必要,将长的URL放在一行上。
Yes: # See details at
# [http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html](http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html)
No: # See details at
# [http://www.example.com/us/developer/documentation/api/content/\](http://www.example.com/us/developer/documentation/api/content/)
# v2.0/csv_file_name_extension_full_specification.html
注意上面例子中的元素缩进; 你可以在本文的:ref:缩进<indentation>`部分找到解释.
3、括号
宁缺毋滥的使用括号
除非是用于实现行连接, 否则不要在返回语句或条件语句中使用括号. 不过在元组两边使用括号是可以的.
Yes: if foo:
bar()
while x:
x = bar()
if x and y:
bar()
if not x:
bar()
return foo
for (x, y) in dict.items(): ...
No: if (x):
bar()
if not(x):
bar()
return (foo)
4、缩进
用4个空格来缩进代码
绝对不要用tab, 也不要tab和空格混用. 对于行连接的情况, 你应该要么垂直对齐换行的元素(见 :ref:行长度 <line_length> 部分的示例), 或者使用4空格的悬挂式缩进(这时第一行不应该有参数):
Yes: # 与起始变量对齐
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,
...
}
No: # 第一行有空格是禁止的
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 2 个空格是禁止的
foo = long_function_name(
var_one, var_two, var_three,
var_four)
# 字典中没有处理缩进
foo = {
long_dictionary_key:
long_dictionary_value,
...
}
5、空行
顶级定义之间空两行, 方法定义之间空一行
顶级定义之间空两行, 比如函数或者类定义. 方法定义, 类定义与第一个方法之间, 都应该空一行. 函数或方法中, 某些地方要是你觉得合适, 就空一行.
6、空格
按照标准的排版规范来使用标点两边的空格
括号内不要有空格.
按照标准的排版规范来使用标点两边的空格
Yes: spam(ham[1], {eggs: 2}, [])
No: spam( ham[ 1 ], { eggs: 2 }, [ ] )
不要在逗号, 分号, 冒号前面加空格, 但应该在它们后面加(除了在行尾).
Yes: if x == 4:
print x, y
x, y = y, x
No: if x == 4 :
print x , y
x , y = y , x
参数列表, 索引或切片的左括号前不应加空格.
Yes: spam(1)
no: spam (1)
Yes: dict['key'] = list[index]
No: dict ['key'] = list [index]
在二元操作符两边都加上一个空格, 比如赋值(=), 比较(==, <, >, !=, <>, <=, >=, in, not in, is, is not), 布尔(and, or, not). 至于算术操作符两边的空格该如何使用, 需要你自己好好判断. 不过两侧务必要保持一致.
Yes: x == 1
No: x<1
当'='用于指示关键字参数或默认参数值时, 不要在其两侧使用空格.
Yes: def complex(real, imag=0.0): return magic(r=real, i=imag)
No: def complex(real, imag = 0.0): return magic(r = real, i = imag)
不要用空格来垂直对齐多行间的标记, 因为这会成为维护的负担(适用于:, #, =等):
Yes:
foo = 1000 # 注释
long_name = 2 # 注释不需要对齐
dictionary = {
"foo": 1,
"long_name": 2,
}
No:
foo = 1000 # 注释
long_name = 2 # 注释不需要对齐
dictionary = {
"foo" : 1,
"long_name": 2,
}
二、注释
1、块注释
“#”号后空一格,段落件用空行分开(同样需要“#”号)
# 块注释
# 块注释
#
# 块注释
# 块注释
2、行注释
至少使用两个空格和语句分开,注意不要使用无意义的注释
# 正确的写法
x = x + 1 # 边框加粗一个像素
# 不推荐的写法(无意义的注释)
x = x + 1 # x加1
3、建议
- 在代码的关键部分(或比较复杂的地方), 能写注释的要尽量写注释
- 比较重要的注释段, 使用多个等号隔开, 可以更加醒目, 突出重要性
app = create_app(name, options)
# =====================================
# 请勿在此处添加 get post等app路由行为 !!!
# =====================================
if __name__ == '__main__':
app.run()
4、文档注释
作为文档的Docstring一般出现在模块头部、函数和类的头部,这样在python中可以通过对象的doc对象获取文档. 编辑器和IDE也可以根据Docstring给出自动提示
- 文档注释以 """ 开头和结尾, 首行不换行, 如有多行, 末行必需换行, 以下是Google的docstring风格示例
# -*- coding: utf-8 -*-
"""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.
"""
- 不要在文档注释复制函数定义原型, 而是具体描述其具体内容, 解释具体参数和返回值等
# 不推荐的写法(不要写函数原型等废话)
def function(a, b):
"""function(a, b) -> list"""
... ...
# 正确的写法
def function(a, b):
"""计算并返回a到b范围内数据的平均值"""
... ...
- 对函数参数、返回值等的说明采用numpy标准, 如下所示
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]
"""
- 文档注释不限于中英文, 但不要中英文混用
- 文档注释不是越长越好, 通常一两句话能把情况说清楚即可
- 模块、公有类、公有方法, 能写文档注释的, 应该尽量写文档注释
三、语句
通常每个语句应该独占一行
不过, 如果测试结果与测试语句在一行放得下, 你也可以将它们放在同一行. 如果是if语句, 只有在没有else时才能这样做. 特别地, 绝不要对 try/except 这样做, 因为try和except不能放在同一行.
Yes:
if foo: bar(foo)
No:
if foo: bar(foo)
else: baz(foo)
try: bar(foo)
except ValueError: baz(foo)
try:
bar(foo)
except ValueError: baz(foo)
四、命名
- 应该避免的名称
- 单字符名称, 除了计数器和迭代器.
- 包/模块名中的连字符(-)
- 双下划线开头并结尾的名称(Python保留, 例如init)
- 命名约定
- 所谓"内部(Internal)"表示仅模块内可用, 或者, 在类内是保护或私有的.
- 用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含).
- 用双下划线(__)开头的实例变量或方法表示类内私有.
- 将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.
- 对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有很多现存的模块使用类似于CapWords.py这样的命名, 但现在已经不鼓励这样做, 因为如果模块名碰巧和类名一致, 这会让人困扰.
Python之父Guido推荐的规范
| Type | Public | Internal |
|---|---|---|
| Modules | lower_with_under | _lower_with_under |
| Packages | lower_with_under | |
| Classes | CapWords | _CapWords |
| Exceptions | CapWords | |
| Functions | lower_with_under() | _lower_with_under() |
| Global/Class Constants | CAPS_WITH_UNDER | _CAPS_WITH_UNDER |
| Global/Class Variables | lower_with_under | _lower_with_under |
| Instance Variables | lower_with_under | _lower_with_under (protected) or __lower_with_under (private) |
| Method Names | lower_with_under() | _lower_with_under() (protected) or __lower_with_under() (private) |
| Function/Method Parameters | lower_with_under | |
| Local Variables | lower_with_under |