模块-import--from...import...
什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
# import加载的模块分为四个通用类别 # 1、使用python编写的代码(.py文件) # 2、已被编译为共享库或DLL的C或C++扩展 # 3、包好一组模块的包 # 4、使用C编写并链接到python解释器的内置模块
为什么要用模块?
因每次退出python解释器然后重新进入,那么你之前定义的函数或变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py 被称为脚本script

为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。
如何使用模块
import --- 示例:在目录创建一个test_module.py文件,则模块名为:test_module
# test_module print('test_module模块') msg = 'Hello world!' def read(): print('test_module-->read()-->msg',msg)
def change():
global msg msg='Hello Jerry'
开始使用 import 导入模块
import test_module
# 结果是:test_module模块
如果多次import同一个模块呢?
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句)
import test_module import test_module import test_module import test_module import test_module # 结果:test_module模块
注意:我们可以从sys.modules中找到当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突。
# 测试一: msg 与 test_module不冲突 import test_module msg = 'hello python' print(test_module.msg)
# 测试一: msg 与 test_module不冲突 import test_module msg = 'hello python' print(test_module.msg) # 测试二:read 与 test_module不冲突 def read(): print('hello python') test_module.read()
# 测试一: msg 与 test_module不冲突 import test_module # msg = 'hello python' print(test_module.msg) # 测试二:read 与 test_module不冲突 def read(): print('hello python') test_module.read() # 测试三:执行test_change()操作的全局变量msg 仍然是test_module中的 msg = 'hello python' test_module.change() print(msg)
首次模块导入的执行过程
首次导入模块test_module时会做三件事:
1.为源文件(test_module模块)创建新的名称空间,在test_module中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2.在新创建的命名空间中执行模块中包含的代码,见初始导入import test_module
# 1 提示:导入模块时到底执行了什么? # 2 # 3 In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function definition enters the function name in the module’s global symbol table. # 4 事实上函数定义也是“被执行”的语句,模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看
3.创建名字my_module来引用该命名空间
#这个名字和变量名没什么区别,都是‘第一类的’,且使用my_module.名字的方式可以访问my_module.py文件中定义的名字,my_module.名字与test.py中的名字来自两个完全不同的地方。
给模块取别名 as 别名
为模块 tset_module 起别名
import test_module as mymodule mymodule.read() # 正常执行 test_module.read() # 执行报错,原因:已启用别名,相当于原来的test_module已经不存在了
示例二:
为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块xmlreader.py和csvreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但采用不同的输入格式。可以编写代码来选择性地挑选读取模块,例如
if file_format == 'xml': import xmlreader as reader elif file_format == 'csv': import csvreader as reader data=reader.read_date(filename)
一行导入多个模块
import os,re,test_module
from... import ...
# 对比import test_module,会将源文件的名称空间'test_module'带到当前名称空间中,使用时必须是test_module.名字的方式 # 而from 语句相当于import,也会创建新的名称空间,但是将test_module中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了
from test_module import read read()
注意:如果当前有定义同名的函数或变量,会将模块内定义的的函数或变量进行覆盖
from test_module import read def read(): print('hello') read()
需要特别强调的一点是:python中的变量赋值不是一种存储操作,而只是一种绑定关系,如下:
from test_module import read,msg msg = 'hello jerry' # 将当前位置的名字msg绑定到了 hello jerry print(msg) # 打印当前的名字 read() # 读取test_module.py中的名字msg,仍然是hello world
这种方式导入也支持别名 as
from test_module import read as testread testread() # 正常运行 read() # 报错
from ... import *
# 可以引入所有的内容,并且调用,但是安全性差 from test_module import * print(msg) read()
为了使用 import * 更安全 接着引入__all__ = [list] 格式必须是__all__ = 列表 ,列表里面是你这个模板文件中的变量名或函数名,且是字符串格式
# test_module __all__ = ['msg'] print('test_module模块') msg = 'Hello world!' def read(): print('test_module-->read()-->msg',msg)
# 改进后,__all__ 里面的变量名或函数名不会被导入 from test_module import * print(msg) # 因为__all__=['msg'] 才会被导入,所以可以引用 read() # 因为没有将read写入到__all__中 所以无法导入
把模块当脚本使用
我们可以通过模块的全局变量__name__来查看模块名: 当做脚本运行: __name__ 等于'__main__'
当做模块导入: __name__= 模块名
作用:用来控制.py
文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
# test_module # __all__ = ['msg'] print('test_module模块') msg = 'Hello world!' def read(): print('test_module-->read()-->msg',msg) def test(): print("这是__main__的作用") if __name__ == '__main__': print('hehehehehe') test()
# 改进后,__all__ 里面的变量名或函数名不会被导入 from test_module import * print(msg) # 因为__all__=['msg'] 不会被导入,所有无法引用 read() test() # if 里的信息不会输出
浙公网安备 33010602011771号