模块是最高级别的程序组织单元,它将程序代码和数据封装起来以便重用。模块往往对应于python程序文件(或是用外部语言如C,Java,C#编写而成的拓展)。
import: 使客户端(导入者)以一个整体获取一个模块
from: 允许客户端从一个模块文件中获取特定的变量名
imp.reload: 在不终止python程序的情况下,提供了一种重新载入模块文件代码的方法。
我为什么使用模块
代码重用
系统命名空间划分
实现共享服务和数据
模块通过使用自包含的变量的包,也就是所谓的命名空间提供了将部件组织为系统的简单的方法。在一个模块文件的顶层定义的所有的变量名都成了被导入的模块对象的属性。导入给予了对模块的全局作用域中的变量名的读取权。
如何组织一个程序
一个python程序包括了多个含有python语句的文本文件。程序是作为一个主体的、顶层的文件来构造的,配合有零个或多个支持的文件,在python中这些文件称作模块。
Python中,顶层文件(又称脚本)包含了程序的主要的控制流程:这就是你需要运行来启动的应用的文件。模块文件就是工具的库。
import如何工作
导入是运行时的运行,程序第一次导入指定文件时,会执行三个步骤:
1. 找到模块文件
模块搜索路径:程序的主目录; pythonpath目录(如果设置了);标准链接库目录;任何.pth文件的内容
.pth文件目录:允许用户把有效的目录添加到模块搜索路径中去,也就是在后缀名为.pth的文本文件中一行一行的列出目录。这些路径配置文件是0和安装相关的高级功能。
2. 编译成位码(需要时)
如果发现字节码文件(.pyc)比源代码旧(更改过源代码),就会在程序运行时自动重新生成字节码,否则跳过。
如果在搜索路径上值发现了字节码文件,没有源代码,就会直接加载字节码(意味着你可以把一个程序只作为字节码文件发 布,而避免发生源代码)
3. 执行模块的代码来创建其所定义的对象
文件中的所有语句会依次执行,从头至尾。(语句执行,def aa: blabla, 只执行def aa, 将方法赋值给aa, blabla是不执行的)
这三个步骤只在程序执行时,模块第一次导入时才会进行。在这之后,导入相同的模块时,会跳过这三个步骤,而只提取内存中已加载的模块对象。从技术上讲,python把载入的模块存储到一个名为sys.modules的表中,并在一次导入的操作的开始检查该表。如果模块不存在,将会启动一个三个步骤的过程。
模块的创建
定义模块,只要把一些python代码输入至文本文件,然后以.py为后缀名保存,任何此类文件都会自动被认为是python模块。在模块顶层指定的所有变量名都会变成其属性,并且可以导出供客户端使用。
对于会执行到不会被导入的顶层文件而言,.py从技术上来讲是可有可无的,但是每次都加上去,可以确保文件类型更醒目,并允许以后可以导入任何文件。
模块的使用
import module:
因为import使一个变量名引用整个模块对象,我们必须通过模块名称来得到该模块的属性(如,module.printer)
from module import printer:
因为from会把变量名复制到另一个作用域,所以它就可以让我们直接在脚本中使用复制后的变量名,而不需要通过模块(如,printer)
from module import *:
当我们使用*时,会取得模块顶层所有赋值了的变量名的copy。从根本上来说,这就是把一个模块的命名空间融入另一个模块中。
它有破坏命名空间的潜质,导入变量和本地作用域中变量同名,变量会被悄悄覆盖掉
以from复制的变量名会变成共享对象的引用,修改一个已取出的可变对象,会影响被导入的模块的对象。
模块命名空间:
模块最好理解为变量名的封装。模块技术命名空间(变量名建立所在的场所),而存在于模块之内的变量名就是模块对象的属性。
文件生成命名空间;
模块语句会在首次导入时执行。Python会建立空的模块对象,并逐一执行该模块文件内的语句。
顶层赋值语句会创建模块属性。
模块的命名空间能通过__dict__或dir(M)获取
模块是独立的作用域
Learning Python, Fourth Edition, by Mark Lutz.