Python语言和标准库(第六章:模块)

模块提供了一种程序之间共享python代码的便捷方式。python提供了几百个模块的库,您可以在脚步中调用它们,也可以创建自己的模块。

本章介绍

研究模块的内部机制

创建一个仅包含函数的模块

在模块中定义类

通过子类扩展类

定义异常来报告错误状态

为模块建立文档

测试模块

将模块作为程序运行

安装模块

5.1研究模块

模块只是一个python源文件,它可以包含变量,类,函数和python脚本中可用到的其他任何元素。

通过使用dir函数可以更好地理解模块,给dir函数传递某个python元素(例如模块)的名称,它将列出该元素的所有属性。例如,要查看_bulitins_的属性,包括内置函数,类和变量,可以使用下面语句

dir(_builtins_)

这将得到类似于下面的输出

对于python这样具有许多特性的语言,它的内置元素非常少。同样可以对导入的模块运行dir函数,例如:

 使用dir有助于研究模块,包括自己创建的模块。

5.1.1导入模块

import module

可以对python自带或者您创建的模块使用这种语法,也可以使用如下所示的另一种语法:

from module import item

这样语法仅导入一个所需的一个item类或者item函数。

如果模块被修改,可以使用imp.reload(module)重新加载模块的新定义。

import module

import imp

imp.reload(module)

使用希望重新加载的模块替换module。

5.1.2查找模块

为了导入一个模块,python解释器首先需要找到他。对于一个模块,python解释器会先找到一个成为module.py的文件,其中module是传递给import语句的模块名称。当找到该模块时,python解释器会编译一个.pyc文件。

python解释器查找模块搜寻路径中的那部分目录。这些目录在sys模块中sys.path变量中列出。

要列出python解析器查找模块的位置,可以在python解释器中打印sys.path变量的值。

5.1.3理解模块

因为python是一个开源包,所以可以得到python解释器和所有模块的源代码。

首先,sys.path变量列出的所有目录中查找到.py结尾的文件。这些文件就是python模块,一些模块只包含函数,一些则包含类和函数,例如,python3.0种parser模块定义一个类:

这个小模块主要由引导用户如何使用该模块的文档组成。这也有助于理解如何创建自己模块。

5.2创建模块和包

创建一个具有函数的模块

 输入下面的python代码,并将文件命名为food.py

这就是一个模块,接下来可以使用python解释器导入该模块,例如:

事例说明:

python使用非常简单的方法定义模块。可以使用任何python源文件作为一个模块,如这个简单的例子所示。

如果不加前缀food会出现问题,使用另一种语法导入模块能够解决这个问题。

5.3使用类

大多数模块定义了一个相关函数或类的集合,python默认能够访问类中的数据,这违反了一些面向对象编程的概念,当好处在于实用。

5.3.1定义面向对象编程

5.3.2创建类

创建一个meal类

meal类的每个实例保存3个数据值:meal类的名称,食物和饮料,meal类默认设置的名称为generic meal等等

5.3.3拓展已有的类

breakfast类通过如下所示的定义拓展meal类

还有

通过lunch类,可以看到setter方法的一些应用。

5.4完成模块

在定义模块的类和函数后,下一步就是完成模块,以使它更合适python用户和python解释器的约定。

完成模块包括很多工作,当至少需要完成以下操作

定义应用模块的错误和异常

定义模块中要输出的项,这定义了模块的公共API

为模块编写文档

测试模块

在模块作为程序执行的情况下提供一个回退函数

5.4.1定义模块特定的错误

大多数情况下,异常类不需要定义任何方法或者初始化任何数据,exception基类所提供的已经足够了。

注意:并非总是如此,例如一个XML解析异常也许应该包括发生初五的行号,以及对错物的描述

5.4.2选择导出哪些内容

使用from形式导入模块时,可以指定导入模块中的哪一项,例如,下面的语句从meal模块导入angrycheexception。

from meal AngryCheException

要从模块导入所有的公有项,可以使用下面格式:

from module_name import *

*告诉python解释器导入模块的全部公有方法。什么是公有方法?作为模块的设计者,您可以选择定义那些项作为能过导出的公有方法。

python解释器有两种方法

如果模块中定义了变量_all_

如果模块中没有定义变量_all_,解释器导入除了名称以 下划线_开头的项目之外的项目。如printIt是公有的,而_printIt不是公有的。

作为最佳实践,总是应该在模块中定义_all_.这样显式控制其他python脚本可以导入的项。为了完成这项工作,可以简单地创建一个文档字符串序列,每个字符串分别对应想要从模块导出的每个项的名称。

在meal模块中:

 这个序列中的每个名称都是一个需从模块导出一个类或者函数

选择要导出的内容很重要,当创建一个模块时,就创建了一个执行一些有用的功能的api。从模块中导出的api定义了模块的用户能实现哪些功能。你希望导出模块的用户能够得到完成工作所需的全部功能,但是不需要导出一切,可能因为一些原因希望排除一些项。

可能要修改的项应该保持私有性,

模块时常有意隐藏复杂的代码(封装)

5.4.3为模块建立文档

为模块建立文档非常重要,否则没有人会知道模块能做哪些事情

浏览模块的文档

在交互模式下启动python解释器,然后像下面import和help命令:

help是您的助手,它可以显示模块的文档。

5.4.4测试模块

创建测试使您可以在修改模块后验证功能仍然有效

任何负责的模块都应该包含执行模块功能的测试函数,测试应该创建模块中定义的类的实例,例如,下面的方法提供了meal模块的一个测试:

将测试函数集成在模块中,这样测试将一直可用。

5.4.5将模块作为程序运行

通常,模块不应自己运行。其他python脚本会从模块中导入项并使用它们。然而,由于任何包含python代码的文件都可以看作一个模块,您可以运行一个模块。

 因为不希望模块自己运行,python为模块定义了一个约定。当一个模块自己运行时它应该执行模块测试。这提供了测试模块的一个简单方式:将python模块作为一个脚本运行。

为了支持这个约定,python提供了一种简单的形式来检测模块是否作为一个程序运行。利用前面给出的test函数,可以使用下面的代码执行对模块的测试:

if _name_=='_main_':
     test()

如果查看标准python模块的源代码,将会反复碰到这样形式。

运行模块

可以通过使用如下命令行,将模块作为程序运行:

该实例将模块作为一个python程序运行,使用前面给出的形式检查这种情况,可以知道模块只运行test函数,您所看到的输出是测试的输出。

注意输出中运行了模块中定义的每个类的实例,并测试angryChefException异常的产生。

如果遵循本节中讲述的设计类的全部指导原则,模块将符合其他python开发人员的期望。而且,模块将在脚本中工作的更好。在下一节的实际应用中可以看这一切,它演示了一个完整的python模块。

5.5创建一个完整的模块

meal模块是根据本章讲述的技术创建一个完整的模块,包含测试,文档,异常,类和函数。注意测试几乎与其他代码一样长。您以后将经常看到这种情况。

构建模块之后,可以将它导入到python脚本中,例如,下面的脚本调用了meal模块中的类和函数:

这个例子使用了标准方法导入模块:

import meal

运行这个脚本时,间看到如下输出:

下一个脚本演示了导入模块的另一种方法:

from meal import *

全部脚本如下:

注意,使用这种导入形式时,不必使用模块名称meal作为前缀就可以调用makeLunch和makeBreakfast函数。

这个脚本的输出与上个脚本输出应该是类似的。

 要十分小心使用的变量名称,示例模块的名称是meal,这意味着不能在其他任何上下文中使用这个名称,例如作为一个变量名称。如果那样做,就覆盖了作为模块的meal的定义,下面的例子演示了这个方法的缺陷。

 

5.6安装模块

python解释器在sys.path变量中列出的目录中查找模块,sys.path变量包括当前目录,所以总是可以使用当前路径中的模块。

大多数情况下,需要将python模块放到site-packages目录中,这个包不是python标准库的一部分。

可以使用三种机制安装模块:

a可以手动创建一个安装脚本或者程序

b可以创建一个针对您的操作系统的安装程序,例如windows上的MSI文件。

c可以使用方便的python distutils包,来创建基于python的安装文件。

 

posted @ 2014-10-28 17:15  以诗答诗  阅读(178)  评论(0编辑  收藏  举报