python开发规范
python开发规范简单记录
python开发规范(转载自:https://www.cnblogs.com/cwp-bg/p/9827529.html)
代码布局
1.1缩进
推荐以4个空格作为一个缩进层次。
1.2表达式和语句中的空格
1.2.1 前导空格(缩进)
最流行的Python缩进方式是仅使用空格,其次是仅使用制表符。对于新的项目,应该仅使用空格而不是制表符。
1.2.2 非前导空格
非前导空格在Python代码中没有意义,但适当地加入非前导空格可以增进代码可读性:
(1)在二元算术、逻辑运算符前后加空格,如:
1 | a = b + c |
(2)在一元前缀运算符后不加空格,如:
1 | if !flag: |
(3)“:”用在行尾时前后皆不加空格,如分支、循环、函数和类定义语言;用在非行尾时后端加空格,如dict对象的定义:
1 | d = {'key': 'value'} |
(4)括号(含圆括号、方括号和花括号)前后不加空格,如:
1 | do_something(arg1, arg2) |
(5)逗号后面加一个空格,前面不加空格。
1.3行的最大长度
每行的最大长度不得超过80个字符的标准。超过80个字符的,建议使用以下方式将单个长行折叠成多个短行:
(1)为长变量名换一个短名,如:
1 | 错误写法: |
(2)在括号(包括圆括号、方括号和花括号)内的分隔符后换行,如:
1 | 示例: |
(3)在长行加入续行符强行断行,断行的位置应在操作符前,如:
1 | if color == WHITE or color == BLACK \ |
1.4空行
输入空行时,一般遵循以下原则:
(1)在import不同种类的模块间加空行;
(2)顶层函数和类的定义之间加空行;
(3)在类与类的定义之间加空行;
(4)在函数与函数的定义之间加空行;
(5)在class定义行和其第一个方法定义之间加空行;
(6)在函数中的逻辑段落间加空行,即把相关的代码紧凑写在一起,作为一个逻辑段落,段落间以空行分隔。
1.5编码
所有的Python脚本文件都应在文件头标上#– coding:utf8 — ;用于设置编辑器,默认保存为utf8格式:
1 | #-*- coding:utf8 -*- |
语句
2.1标准头部
一般情况下使用如下标准头部语句:
1 | #!/usr/bin/python |
如果需要使用自定义的Python编译环境,可使用类似如下的头部语句:
1 | #!/usr/bin/env python2.7 |
说明:该行语句的作用是帮助内核找到Python解释器,但通常在Python导入模块时被忽略;只有直接执行单个文件时,该语句才是必要的。
2.2导入(import)
2.2.1通常应该在单独的行中导入(import)
例如“正确写法1”;若需要在一行中从一个模块导入多个类,可参照“正确写法2”:
1 | 错误写法: |
2.2.2导入语句的位置及导入顺序
通常将import语句放置在文件的顶部,仅在模块注释和文档字符串之后,在模块的全局变量和常量之前。导入语句应该有顺序地成组安放:
(1)首先,导入标准库(内置模块);
(2)其次,导入第三方模块(引用的第三方包);
(3)最后,导入自己开发的项目中的其他模块;
在每组导入之间放置一个空行。
2.2.3导入类的方法
从一个包含类的模块中导入类时,通常可以写成这样:
1 | 示例: |
如果上述写法导致了本地名字冲突,那么就这样写:
1 | 示例: |
然后使用MyClass.MyClass和foo.bar.YourClass.YourClass方式即可。
2.3赋值
对于赋值语言,主要是不要做无谓的对齐,如:
本文采用 CC NONE 4.0 许可协议,著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1 | 错误写法: |
2.4分支和循环
各种分支和循环语句不要写成一行,如:
1 | 错误写法: |
注释
代码修改时,始终优先更新注释。注释应该是完整的句子,如果注释是一个短语或句子,首字母应该大写,除非他是一个以小写字母开头的标识符(如果以中文注释可忽略此要求)。
3.1注释块
注释块通常用于跟随着一些代码并和这些代码有着相同的缩进层次。注释块中每行均以“#”和一个空格开始。注释块内的段落间以仅含单个“#”的行分割。注释块上下方最好各有一空行。
3.2行内注释
行内注释是和语句在同一行的注释。行内注释应该至少用两个空格和语句分开,且应该以“#”和单个空格开始,如:
1 | 示例: |
3.3文档字符串
为所有公共模块、函数、类和方法编写文档字符串。文档字符串对非公开的方法不是必要的,但应该有一个注释描述这个方法的作用。这个注释应该在“def”行之后。
一定注意,多行文档字符串结尾的”””应该单独成行,例如:
1 | 示例: |
对单行的文档字符串,结尾的”””在同一行也可以,例如:
1 | """Return a foobang""" |
3.4版本注记
版本注记可以参照如下示例代码:
1 | 示例: |
3.5模块注释
每个模块注释都应该包含下列项,依次是:
(1)版权声明;
(2)模块注释内容,包括模块描述、模块中的类和方法的描述、版本及维护信息等;
(3)作者声明,标识文件的原作者;
1 | 示例: |
3.6函数和方法注释
任何函数或方法都需要一个文档字符串,对于任何外部可访问的函数或方法,文档字符串尤为重要。
文档字符串应该包含函数的作用,以及参数、输入和输出的详细描述:
(1)Args:输入参数的具体描述;如果参数要求特定的数据类型或者设置了参数的默认值,那么应该在文档字符串中明确说明;
(2)Returns:输出(返回)数据的具体描述;
(3)Raises:应该列出该函数可能触发的所有异常;
1 | 示例: |
3.7类注释
类定义下方必须有一个用于描述该类的文档字符串(docString)。如果类中有公共属性(Attributes),那么文档字符串中应该说明这些公共属性的意义。
1 | 示例: |
命名约定
4.1说明:命名约定
禁止使用字符“l”、“O”或“I”作为单字符的变量名。在某些字体中无法将这些字符与数字1和0区分开。
4.2模块名
模块名应该是不含下划线的、简短的、全小写的名字;对于默认仅在包(Packages)内使用的模块,可以加一个下划线前缀,如:
1 | 示例: |
4.4类名
类名使用CapWords约定(单词首字母大写,不使用下划线连接单词,也不加入C、T等前缀);内部使用的类需要在名称前加一个前导下划线,如:
1 | 示例: |
4.5异常名
异常名使用CapWords命名规则(单词首字母大写,不使用下划线连接单词)。
4.6变量、常量、全局变量名
Python一般通过“from M import *”来从模块中导入相关内容(变量、类、函数等),必须用一个下划线作全局变量(内部函数或类)的前缀防止其被导出(exporting)。
4.6.1常量
常量名的所有字母均大写,由下划线连接各个单词,如:
1 | 示例: |
4.6.2变量
(1)变量名全部小写,由下划线连接各个单词,如:
1 | 示例: |
(2)不论是类成员变量还是全局变量,均不使用m或g前缀。私有类成员使用单一下划线前缀标识;
(3)变量名不应带有类型信息,因为Python是动态类型语言;如iValue、names_list、dict_obj等都是不好的命名。
4.6.3全局变量
必须用一个下划线作为全局变量的前缀防止其被导出。
4.7函数名
函数名应该为小写,可用下划线风格单词以增加可读性。
4.8方法名和实例变量
大体上和函数命名规则相同:通常使用小写单词,必要时用下划线分隔增加可读性。
如果是不打算对外公开的内部方法和实例,需要在名称开头使用一个前导下划线。
使用两个前导下划线以表示类私有成员的名字。通常双前导下划线仅被用于避免含子类的类中的属性名冲突。
4.9特定的命名方式
主要是指__xxx__形式的系统保留字命名法。项目中也可以使用这种命名,它的意义在于这种形式的变量是只读的,这种形式的类成员函数尽量不要重载。如:
1 | 示例: |
继承的设计
始终要确定一个类中的方法和实例变量是否要被公开。通常,永远不要将数据变量公开,除非你实现的本质上只是记录,人们总是更喜欢为类提供一个函数的接口来实现数据变量的修改。
同样,确定你的属性是否应为私有的。私有和非私有的区别在于:前者永远不会被用在一个派生类中,而后者可能会。你应该在大脑中就用继承设计好了你的类:
(1)私有属性必须有两个前导下划线,无后置下划线;
(2)非公有属性必须有一个前导下划线,无后置下划线;
(3)公共属性没有前导和后置下划线,除非它们与保留字冲突,在此情况下,单个后置下划线比前置或混乱的拼写要好,例如:class_优于klass。
设计建议
单个元素(singletons)的比较,如None应该使用“is”或“is not”。当你本意是“if x is not None”时,对写成“if x”要小心。例如当你测试一个默认为None的变量或参数是否被设置为其它值时,这个其它值也许在布尔上下文(Boolean context)中是False。
基于类的异常总是好过基于字符串的异常。模块和包应该定义它们自己的域内特定的基异常类,基类应该是内建的Exception类的子类,还始终包含一个类的文档字符串。例如:
1 | 示例: |
使用字符串方法(methods)代替字符串模块,除非必须向后兼容Python 2.0以前的版本。字符串方法总是非常快,而且和unicode字符串共用同样的API(应用程序接口),在检查前缀或后缀时避免对字符串进行切片。用startswith()和endswith()代替,因为这样出现错误的机率更小。例如:
1 | 错误写法: |
特殊情况下,如果你的代码必须工作在Python 1.5.2,对象类型的比较应该始终用isinstance()代替直接比较类型,例如:
1 | 错误写法: |
检查一个对象是否是字符串时,谨记它也可能是unicode字符串!在Python 2.3中,str和unicode有公共的基类basestring,所以你可以这样做:
1 | if isinstance(obj, basestring): |
在Python 2.2类型模块为此定义了StringTypes类型,例如:
1 | #!/usr/bin/Python |
对序列(字符串、列表、元组)而言,使用空列表是false这个事实,因此“if not seq”或“if seq”比“if len(seq)”或“if not len(seq)”好。书写字符串文字时不要依赖于有意义的后置空格。这种后置空格在视觉上是不可辨别的,并且有些编辑器会将它们修整掉。不要用“==”来比较布尔型的值以确定是True或False(布尔型是Python2.3中新增的):
1 | 错误写法: |