1、第7章 模块和包 Python程序是由包、模块、函数组成的。其中,包是由一系列模块组成的集合,而模块是处理某一类问题的函数或(和)类的集合。7.1 命名空间 命名空间是从变量或标识符的名称到对象的映射。当一个名称映射到一个对象上时,这个名称和这个对象就绑定了。我们可以把命名空间理解为一个容器,在这个容器中可以装许多名称。命名空间的分类命名空间的分类 Python中有三类命名空间:内建命名空间、全局命名空间和局部命名空间7.1.2 命名空间的规则 赋值语句(包括显式赋值和隐式赋值)会把名称绑定到指定对象中,赋值的地方决定名称所处的命名空间。函数、类定义会创建新的命名空间。Python搜索一个名称
2、的顺序是“LEGB”。第一层是L(local),表示在一个函数定义中,而且在这个函数里面没有再包含函数的定义。第二层是E(enclosing function),表示在一个函数定义中,但这个函数里面还包含有函数的定义,其实L层和E层只是相对的,这两层空间合起来就是上面所说的局部命名空间。第三层是G(global),表示一个模块的命名空间,也就是说在一个.py文件中,且在函数或类外构成的一个空间,这一层空间对应上面所说的全局命名空间。第四层是B(builtin),表示Python解释器启动时就已经加载到当前编程环境中的命名空间,之所以叫builtin是因为在Python解释器启动时会自动载入_b
3、uiltin_模块,这个模块中的list、str等内置函数就处于B层的命名空间中,这一层空间对应上面所说的内建命名空间。7.2 模块 在Python中,模块就是一个包含变量、函数或类的定义的程序文件,除了各种定义之外,还可包含其他的各种Python语句。在大型系统中,往往将系统功能分别使用多个模块来实现或者将常用功能集中在一个或多个模块文件中,然后在顶层的主模块文件或其它文件中导入使用。Python本身也提供了大量内置模块,并可集成各种扩展模块。7.2.1 导入模块 模块需要先导入,然后才能使用其中的变量或函数。可使用import或from语句来导入模块,基本格式如下。import 模块名称
4、import 模块名称 as 新名称 from 模块名称 import 导入对象名称 from 模块名称 import 导入对象名称 as 新名称 from 模块名称 import*7.2.2 7.2.2 导入与执行语句导入与执行语句 import和from语句在执行导入操作时,会执行被导入的模块。模块中的赋值语句执行时创建变量,def语句执行时创建函数对象。总之,模块中的全部语句都会被执行,且只执行一次。当再次使用import或from语句导入模块时,不会执行模块代码,只是重新建立到已经创建的对象的引用而已。所以,import和from语句是隐性的赋值语句。Python执行import语句时
5、,创建一个模块对象和一个与模块文件同名的变量,并建立变量和模块对象的引用。Python执行from语句时,会同时在当前模块和导入模块中创建同名变量,并引用模块在执行时创建的对象。7.2.3 import及from的使用 在使用import导入模块时,模块中的变量名使用“模块名.“作为限定词,所以不存在歧义,即使与其它模块变量同名也没有关系。在使用from时,当前模块的同名变量引用了模块内部的对象。在遇到与当前模块或其它模块变量同名时,使用时应特别注意。1使用模块内的可修改对象 使用from导入模块时,可以直接使用变量名引用模块中的对象,避免了输入“模块名.”作为限定词。这种便利有时也会遇到麻烦
6、。2使用from导入两个模块中的同名变量 在下面的两个模块test3.py和test4.py中包含了同名的变量名。7.2.4 重新载入模块 很多时候,再次使用import和from导入模块时,其本意通常是重新执行模块代码,恢复相关变量到模块执行时的状态。显然,这种愿望通过再次使用import和from导入是无法达到的。因此,Python在imp模块中提供了reload函数来重新载入并执行模块代码。使用reload重载模块时,如果模块文件已经被修改,则会执行修改后的代码。reload函数用模块变量名作为参数,重载对应模块,所以reload重载的必须是使用import语句已经导入的模块。7.2.5
7、 嵌套导入模块 Python允许任意层次的嵌套导入模块。每个模块都是一个名字空间,嵌套导入意味着名字空间的嵌套。在使用模块变量名时,则需要依次使用模块变量名作为限定符。7.2.6 模块对象属性和命令行参数 在导入模块时,Python会使用模块文件创建一个模块对象。模块中引用的各种对象的变量名称为对象的属性。Python也为模块对象添加一些内置的属性。可使用dir函数来查看对象属性。7.2.7 模块搜索路径 在导入模块时,Python会执行下列三个步骤。搜索模块文件:在导入模块时,省略了模块文件的路径和扩展名,因为Python会按特定的路径来搜索模块文件。必要时编译模块:找到模块文件后,Pyth
8、on会检查文件的时间戳,如果字节码文件比源代码文件旧,即源代码文件做了修改,Python会执行编译操作,生成最新的字节码文件。如果字节码文件时最新的,则跳过编译环节。如果在搜索路径中只发现了字节码而没有源代码文件,则直接加载字节码文件。如果只有源代码文件,Python则直接执行编译操作,生成字节码文件。执行模块:执行模块的字节码文件。文件中所有的可执行语句都会被执行,所有的变量在第一次赋值时被创建,函数对象也在执行def语句时创建。如果有输出也会直接显示。7.3 包 在大型系统中,通常会根据代码功能将模块文件放在多个目录中。在导入这种位于目录中的模块文件时,需要指定目录路径。Python将存放
9、模块文件的目录称为包。包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用程序执行环境。包可以解决如下问题:把命名空间组织成由层次的结构;允许程序员把有联系的模块组合到一起;允许程序员使用有目录结构而不是一大堆杂乱无章的文件;解决有冲突的模块名称。7.3.1 包的基本结构7.3.2 包的导入 包的导入包括绝对路径导入和相对路径导入两种。小 结(1)命名空间。命名空间是从名称到对象的映射。Python中有三类命名空间:内建命名空间、全局命名空间和局部命名空间。不同的命名空间中的名称是没有关联的。(2)模块。模块是把一组相关的名称、函数、类或它们的组合组织到一个文件中。一个文件被看作一个独立的模块,一个模块也可以被看作一个文件。模块的文件名就是模块的名字加上扩展名.py。(3)模块导入。模块导入可以使用import语句导入整个模块或者使用from-import语句导入指定模块的变量、函数或者类等。(4)包。包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用程序执行环境。