3.4 基本风格指南

注释

注释对于自己和后来人来说都是非常重要的,特别是对那些很久没有被动过的代码而言,注释更显得有用了。既不能缺少注释,也不能过度使用注释。尽可能使注释简洁明了,并放在最合适的地方。这样注释便为每个人节省了时间和精力。记住,要确保注释的准确性。

文档

Python还提供了一个机制,可以通过doc特别变量,动态获得文档字串。在模块、类声明、或函数声明中第一个没有赋值的字符串可以用属性obj.doc来进行访问,其中obj是一个模块、类、或函数的名字。这在运行时也可以进行!

缩进

因为缩进对齐有非常重要的作用,你得考虑用什么样的缩进风格才让代码容易阅读。在选择要空的格数的时候,常识也起着非常大的作用。

1个或2个可能不够,很难确定代码语句属于哪个块。

8〜10个可能太多,如果代码内嵌的层次太多,就会使得代码很难阅读。4个空格非常的流行,更不用说Python的创造者也支持这种风格。5和6个也不坏,但是文本编辑器通常不支持这样的设置,所以也不经常使用。3个和7个是边界情况。

当使用制表符Tab的时候,请记住不同的文本编辑器对它的设置是不一样。如果你的代码会存在并运行在不同的平台上,或者会用不同的文本编辑器打开,建议你不要使用Tab。

选择标识符名称

好的判断也适用于选择标识符名称,请为变量选择短而意义丰富的标识符。虽然变量名的长度对于今天的编程语言不再是一个问题,但是使用简短的名字依然是个好习惯,这个原则同样使用于模块 (Python文件)的命名。

Python风格指南

Guido van Rossum在多年前写下Python代码风格指南。目前它已经被至少3个PEP代替:7(C代码风格指南)、8 (Python代码风格指南)和257(文档字符串规范)。这些PEP被归档、维护并定期更新。

渐渐地,你会听到“Pythonic”这个术语,它指的是以Python的方式去编写代码、组织逻辑和对象行为。更久以后,你才会真正理解它的含义。PEP 20写的是Python之禅,你可以从那里开始探索 “Pythonic”真正含义的旅程。如果你不能上网,但想看到它,那就从你的Python解释器输入import this然后回车。下面是一些网上资源。

www.Python.org/doc/essays/styleguide.html

www.Python.org/dev/peps/pep-0007/

www.Python.org/dev/peps/pep-0008/

www.Python.org/dev/peps/pep-0020/

www.Python.org/dev/peps/pep-0257

3.4.1 模块结构和布局

用模块来合理组织你的Python代码是简单又自然的方法。你应该建立一种统一且容易阅读的结构,并将它应用到每一个文件中去。下面就是一种非常合理的布局。

(1)起始行(Unix)

(2)模块文档

(3)模块导入

(4)变量定义

(5)类定义

(6)函数定义

(7)主程序

(1) 起始行

通常只有在类Unix环境下才使用起始行,有起始行就能够仅输入脚本名字来执行脚本,无需直接调用解释器。

(2) 模块文档

简要介绍模块的功能及重要全局变量的含义,模块外可通过module.doc访问这些内容。

3.4 基本风格指南 - 图1

图 3-1 典型Python文件结构

(3) 模块导入

导入当前模块的代码需要的所有模块;每个模块仅导入一次(当前模块被加载时);函数内部的模块导入代码不会被执行,除非该函数正在执行。

(4) 变量定义

这里定义的变量为全局变量,本模块中的所有函数都可直接使用。从好的编程风格角度说,除非必须,否则就要尽量使用局部变量代替全局变量,如果坚持这样做,你的代码就不但容易维护,而且还可以提高性能并节省内存。

(5) 类定义语句

所有的类都需要在这里定义。当模块被导入时class语句会被执行,类也就会被定义。类的文档变量是class.doc

(6) 函数定义语句

此处定义的函数可以通过module.function()在外部被访问到,当模块被导入时def语句会被执行,函数也就都会定义好,函数的文档变量是function.doc

(7) 主程序

无论这个模块是被别的模块导入还是作为脚本直接执行,都会执行这部分代码。通常这里不会有太多功能性代码,而是根据执行的模式调用不同的函数。

3.4 基本风格指南 - 图2核心风格:主程序调用main()函数

主程序代码通常都和你前面看到的代码相似,检查name变量的值然后再执行相应的调用(参阅下一个核心笔记)。主程序中的代码通常包括变量赋值、类定义和函数定义,随后检查name来决定是否调用另一个函数(通常调用main()函数)来完成该模块的功能。主程序通常都是做这些事。(我们上面的例子中使用test()而不是main()是为了避免你在读到核心笔记前感到迷惑。)不管用什么名字,我们想强调的是:这儿是放置测试代码的好地方。我们在3.4.2小节中曾经说过,大部分的Python模块都是用于导入调用的,直接运行模块应该调用该模块的回归测试代码。

很多项目都是一个主程序,由它导入所有需要的模块。所以请记住,绝大部分的模块创建的目的是为了被别人调用而不是作为独立执行的脚本。我们也很可能创建一个Python库风格的模块,这种模块的创建目的就是为了被其他模块调用。总之,只有一个模块,也就是包含主程序的模块会被直接执行,或由用户通过命令行执行,或作为批处理执行,或由Unix cron任务定时执行,或通过Web服务器调用,或通过GUI执行。

时刻记住一个事实,那就是所有的模块都有能力来执行代码。最高级别的Python语句——也就是说,那些没有缩进的代码行——在模块被导入时就会执行,不管是不是真的需要执行。由于有这样一个“特性”,比较安全的写代码的方式就是除了那些真正需要执行的代码以外,几乎所有的功能代码都在函数当中。再说一遍,通常只有主程序模块中有大量的顶级可执行代码,所有其他被导入的模块只应该有很少的顶级执行代码,所有的功能代码都应该封装在函数或类当中。(参阅核心笔记了解更多信息)

3.4 基本风格指南 - 图3核心笔记:name指示模块应如何被加载

由于主程序代码无论模块是被导入还是被直接执行都会运行,我们必须知道模块如何决定运行方向。一个应用程序可能需要导入另一个应用程序的一个模块,以便重用一些有用的代码 (否则就只能用拷贝粘贴那种非面向对象的笨拙手段)。这种情况下,你只想访问那些位于其他应用程序中的代码,而不是想运行那个应用程序。因此一个问题出现了,“Python是否有一种方法,能在运行时检测该模块是被导入还是被直接执行呢?”答案就是…(掌声雷动)…没错!name系统变量就是正确答案。

  • 如果模块是被导入,name的值为模块名字;

  • 如果模块是被直接执行,name的值为‘main’。

3.4.2 在主程序中书写测试代码

优秀的程序员和软件工程师,总是会为我们的应用程序提供一组测试代码或者简单教程。对那些仅仅为了让别的程序导入而创建的模块来说,Python有效地简化了这个任务。这些模块理论上永远不会被直接执行,那么,在这个模块被直接执行时进行系统测试岂不妙哉?设置起来难吗?一点儿也不难。

测试代码仅当该文件被直接执行时运行,也就是说,不是在被别的模块导入时。上文及核心笔记中提到如何判断一个模块是被直接运行还是被导入的。我们应该利用name变量这个有利条件。将测试代码放在一个叫做main()或test()(或者你随便取个名字)的函数中,如果该模块是被当成脚本运行,就调用这个函数。

这些测试代码应该随着测试条件及测试结果的变更及时修改,每次代码更新都应该运行这些测试代码,以确认修改没有引发新问题。只要坚持这样做,你的代码就会足够健壮,更不用提验证和测试新特性和更新了。

在主程序中放置测试代码是测试模块的简单快捷的手段。Python标准库中还提供了unittest模块,有时候它被称为PyUnit,是一个测试框架。如何使用unittest超出了本书的范围,不过当需要对一个大系统的组件进行正规系统的回归测试时,它就会派上用场。