首页 > 代码库 > 模块和包
模块和包
一.模块
1.什么是模块
一个模块就是包含了python 定义和声明的文件,文件名就是模块名加.py后缀
2.模块的作用
方便管理,使功能得到重复利用
3.使用模块
3.1 模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行,第一次导入后就已将模块名加载到内存中了。
3.2 每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当作全局名称空间,编写自己的模块时不用担心与使用者的全局变量发生冲突。
3.3 首次导入模块my_moudle时会做三件事:
1.为源文件(my_moudle模块)创建新的名称空间,在my_moudle中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2.在新创建的命名空间中执行模块中包含的代码,见初始导入import my_moudle
3.创建名字my_moudle来引用该命名空间
3.4 为模块起名
#import my_module as sm #print(sm.money)
3.5 在一行中导入多个模块
#import sys,os,re
3.6 from...import
#from my_module import read1,read2 #这样可以直接用模块中的名字 #如果当前文件中有和module中一样的名字比如都有read(),则会被覆盖
注意:python中的变量赋值不是一种存储操作,而只是一种绑定关系
#from my_moudle import money,read1 #money=100 #将当前位置的名字money绑定到了100 #print(money) #打印当前的名字 #read1() #读取my_moudle.py中的名字money,仍然为1000 ‘‘‘ #from the my_moudle.py #my_moudle->read1->money 1000 ‘‘‘
3.7 支持as,也支持多行导入
# from my_moudle import read1 as read # from my_moudle import (read1, # read2, # money)
3.8 from my_moudle import * 把my_moudle中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
#from my_moudle import * #将模块my_moudle中所有的名字都导入到当前名称空间 #print(money) #print(read1) #print(read2) #print(change) #执行结果: #from the my_moudle.py #<function read1 at 0x1012e8158> #<function read2 at 0x1012e81e0> #<function change at 0x1012e8268>
#在my_moudle.py中新增一行 #__all__=[‘money‘,‘read1‘] #这样在另外一个文件中用from my_moudle import *就这能导入列表中规定的两个名字
3.9考虑到性能的原因,每个模块只被导入一次,放入字典sys.module中,如果你改变了模块的内容,你必须重启程序,python不支持重新加载或卸载之前导入的模块
#def func1(): # print(‘func1‘) #import time,importlib #import aa #time.sleep(20) # importlib.reload(aa) #ctrl + s 可以更改 #aa.func1()
4.0把模块当作脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于‘__main__‘
当做模块导入:
__name__= 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == ‘__main__‘:
def fib(n): a, b = 0, 1 while b < n: print(b, end=‘ ‘) a, b = b, a+b print() if __name__ == "__main__": print(__name__) num = input(‘num :‘) fib(int(num))
4.1 模块搜索路径
内存中已经加载的模块->内置模块->sys.path路径中包含的模块
4.2 编译python文件
为了提高模块的的加载速度,python解释器会在__pycache__目录中下缓存每个模块编译后的版本,格式为:module.version.pyc。通常会包含python的版本号。例如,在CPython3.3版本下,my_moudle.py模块会被缓存成__pycache__/my_moudle.cpython-33.pyc。这种命名规范保证了编译后的结果多版本共存。
二.包
2.1
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
2.2
注意:
1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
3.对比import item 和from item import name的应用场景:
如果我们想直接使用name那必须使用后者。
2.3 from ..import ...
需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
2.4 __init__.py文件
不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。
模块和包