前言
我在前面很多文章中提及过,好的代码绝不仅仅包含能够实现一个项目、一个功能那么简单。在开发一个系统的过程中需要重点考虑代码的可复用性、设计模式,这样能够让后期维护变的更加方便简单。
除了高级的设计模式之外,编程过程中规范的代码也是至关重要的,它不仅能够让周围同事更加容易的阅读和理解、提高团队合作效率,此外,还可以避免因为不规范而造成的细节错误,举个例子,多线程之间存在变量共享问题,如果在写代码时考虑不周到会引起变量的重复写入,进而造成一系列不容被发现的问题。因而,保证良好的开发规范,能够减少很多容易疏忽的错误,为后期代码调试减少很多不必要的工作量。
本文首先介绍一些常用的Python代码分析工具pylint,然后结合《Google开源项目风格指南》提炼、介绍一下Python开发需要着重注意的一些语言规范。
pylint
简介
pylint是一款Python代码分析工具,在企业项目开发部署中,也常用作代码规范的代码的静态检查。例如,变量名称格式是否正确、检查代码长度等,它的主要功能可以分为如下几个方面:
- 代码规范
- 错误检测
- 协助重构
- 持续集成
- ……
其中较为常用的就是代码规范和错误检测,能够按照PEP8编程风格指导对代码进行静态检查,并提示哪里有错误?哪里不够规范?
使用
第一步:首先需要需要按照pylint,
$ pip install pylint
第二步:生成默认配置文件,
$ pylint --persistent=n --generate-rcfile > pylint.conf
然后会生成一个pylint.conf
文件,主要包含pylint的一些配置项,这一块可以忽略。
第三步:代码分析
pylint可以单独分析一个文件,也可以分析当前目录下所有子目录的文件,
分析单个文件,
$ pylint test.py
检查、分析单个文件它会详细的列出4个等级的信息报告,分别是,
- convention
- refactor
- warning
- error
也可以分析整个目录下所有文件,
$ pylint directory_name/
确认后会详细的列出每一个出问题的地方,已经出现了什么问题。
经过pylint的代码分析之后,可以按照它的提示进行修改代码规范,能够极大的提高代码质量。由于pylint是一款很优秀的Python代码静态分析工具,目前很多知名的开发工具都已经集成或者通过简单的配置拥有pylint的功能,例如,pycharm、vscode等。
Google开源项目风格指南
pylint有很多优点,
- 检查速度快
- 使用简单
- 分析深入
- ……
但是它也有一些不足之处,例如,它严格的按照PEP8进行规范,有很多是不必要的告警,pylint提示的信息过多,这样会无从下手,我们要选择性的抑制或者忽略告警信息。
在很多知名的大企业中都有一套自己的代码开发规范,当然它们很多地方都是有相同之处的,而不是天壤之别的差异。
提高这里就引出了这一节的主角--Google,我们都知道Google是开源社区的主要贡献者之一,它们开源了很多知名且优质的项目,例如,近两年比较火的TensorFlow。它们在开源项目中针对不同语言都有一套明确的风格指南,本文从《Google开源项目风格指南》中提炼出一些比较有价值的Python编程规范,希望能够对各位在Python开发中有所帮助。
Python语言规范
- 导入包:使用模块全路径来导入包,这样能够避免模块名称相同而造成的冲突
- 异常处理:首先,
raise
抛出异常抛出异常时应该使用已有的异常类或者自定义异常类,例如,raise MyException("Error message")
,避免抛出一串不知所云的字符串,例如,raise "Error message"
。其次,用except
捕获异常时避免使用Exception
这类泛泛的异常。以上两点主要为了帮助后期调试,能够清楚抛出的什么类型的异常,捕获了什么样的错误,有助于调试。 - 全局变量:尽量避免使用全局变量,可以用类变量替代。
- 列表推导:在简单的情况下鼓励使用列表推导式,复杂的情况下避免使用列表推导式,难以阅读,例如,下方,映射表达式, for语句, 过滤器表达式中简单的情形可以用一行列表推导式代替多行代码。
result = [] for x in range(10): result.append(x * x) result = [x ** 2 for x in range(10)]
- 生成器:生成器可以有效的节省内存占用情况,可以按需使用生成器。
- 默认参数值:定义一个函数式,我们为了应对某些特例情况而添加几个参数,但是大多数情况下是用不到的,我们可以采用默认参数值的方式应对这些特例调用问题,这里需要注意,默认参数值不要使用可变对象,例如,列表、字典等。
- True/False的求值:尽量的使用隐式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被认为是false,我们在获取这些返回值时可以用隐式的false,例如,返回的
foo
是一个空列表,我们可以用if foo:
来判断它是否为“空”,而不是if foo==[]:
,这样不仅更加易读,而且能够避免犯错。 - 过时的语言特性:在很多代码里面习惯于使用filter、map、reduce这类语言特性,尽可能使用列表推导或者for循环替代。
以上介绍的是Python在语言方面的规范,也就是说不用这种方式也可以同样实现对应的功能,但是通过上述语言规范能够更多的避免细微之处带来的错误,下面就来介绍一下Python风格规范。
Python风格规范
首先来看一下风格这个词汇的概念,
风格是指具有独特于其他人的表现,打扮,行事作风等行为和观念。
也就是说它是一个个性化的概念,对于Python编程,每个人都有自己的风格,你可以按照自己独特的风格去编写代码,这样不会像语言规范那么严格,疏忽之处容易造成错误。Python风格规范更侧重于代码阅读中的地位,良好的风格规范能够让代码更加容易阅读,能够对团队协作、后期维护提供强有力的支撑。
- 行长度:代码行长度不要超过80。使用过Pycharm的应该都知道,它有一个代码长度指引线,也就是说按照代码风格规范不要超过这个长度,但是pycharm默认的代码长度是120,这里有一些误导人,在很多大型公司这个数值应该设定为79。pycharm可以通过Editor->Code Style进行修改,vscode可以通过
editor.rulers
进行设定修改。 - 括号:尽量少使用括号,尤其是在条件语句、返回语句中。
- 空行:顶级定义,例如,函数、类定义之间空两行,类定义和第一个方法、其他方法之间空一行。
- 空格:第一,括号内不要使用空格;第二,不要在逗号、冒号、分号前面加空格,应该在它们后面加上空格;第三、运算符两边加空格。
- Shebang:不要纠结于这个词的含义,它只是一种用法,具体而言,在main主文件前加上
#!/usr/bin/python2
,或者#!/usr/bin/python3
,这是由于#!
能够帮助内核找到Python解释器,当然,这只有在执行文件中才有必要,默认main
为执行文件。 - 类继承:如果定义的类不从其他类继承,可以显式的从
object
继承,也就是说用class Sample(object):
,而不是class Sample:
。 - 字符串:避免使用+或者+=来累加字符串,由于字符串是不可变对象,如果这样累加会导致创建不必要的临时对象,非线性的增加运行时间。
- 文件和sockets:在文件和sockets结束时,应该显式的关闭它,这里推荐使用
with
语句,这样就避免重复的写关闭语句,也防止遗忘编写关闭语句。
with open("test.log", 'r') as fp: lines = fp.readlines()
- TODO注释:我在前面介绍vs code的文章中提到了TODO注释,这是一个良好的习惯,对临时代码进行TODO注释或者FIXME注释,能够很容易定位到即将解决的问题所在处。
- 导入模块格式:每个导入应该独占一行。
# 正确 import os import sys # 错误 import os, sys
- 命名:第一、模块名、包名称、方法名、函数名、实例变量名、函数参数名、局部变量名这些应该使用小写字母加下划线的方式,例如,
function_name
;第二、类名、自定义异常名,应该采用驼峰的命名方式,例如,ClassName;第三、全局变量名应该使用大写字母加下划线的方式,例如,GLOBAL_VAL_NAME。
注意,Python没有像Java、C++这些严格的受保护变量和私有变量的概念,但是有一些约定成熟的使用方式,例如单下划线(_)用于表示模块变量或者protected变量。双下划线(__)表示实例变量或者类的私有变量。
下面有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 |
- Main:main文件一般用于执行文件,但是这个文件也应该是可以在其他地方导入的,因此需要在main文件中加入
if name__ == '__main'
,这样当直接执行时可以运行主程序,当导入时则不会运行。
结语
上述主要根据《Google开源项目风格指南》提取、总结了一些常用的Python语言规范和风格规范,养成的良好的开发习惯,能够大大减少开发过程中遇到的问题,也许在刚开始去尝试记忆这些事会觉得非常繁琐,但是久而久之、潜移默化之中就养成了这样的习惯,这样就会觉得并不是负担,而且能够提升代码的可靠性和可阅读性。
本文只是抽取了其中部分常用的规范,如果希望进行深入的了解可以访问下方连接查看《Google开源项目风格指南》进行系统学习。
https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/contents/