模块以及包
一:模块#
【1】:
(1)定义:模块是一系列功能的集合体
(2)好处:
(1)大量的代码分模块 组织结构更加清晰
(2)不同的文件对应不同的功能 调用方便
(3)模块拿来就可以使用 提升开发效率
【2】:
(1)来源方式:
(1)python自定义的模块
(2)第三方模块
(4)自己手工定义的
(2)表现形式:
(1)一个.py文件即为一个模块
(2)被编译为共享库或DLL的C或者C++扩展
(3)把一系列模块组织到一起的文件夹
(4)使用C语言编写的内置模块
【3】
(1)模块的调用方式
import + 模块名
PS:在模块导入的注意事项
(1)执行文件: import + 模块名
(2)被导入模块:import 后面跟的模块名
例如:

# 执行文件 import spam res = spam print(res) # <module 'spam' from 'D:\\Workstaion\\Practice Code\\spam.py'> # 被导入模块 print('start from the spam.py') money=1000 def read1(): print('spam模块:',money) def read2(): print('spam模块') read1() def change(): global money money=0 print('end from the spam.py')
PS:其只会执行第一次导入的模块 不会执行第一次之后的模块
(2)模块导入流程图
(1)首先会执行模块代码
(2)将模块代码存放入模块开辟的名称空间中
(3)执行文件本地名称空间存放指向模块的名字
如图所示:
(3)被导入模块拥有自己独立名称空间
例如:

money = 100 print(spam.money) # 1000 指名道姓就是读取spam这个模块里代码

import spam money = 100 read1 = '本地文件代码' print(spam.read1) # <function read1 at 0x0000000002819A60> 通过内存地址取值 print(spam.read1()) # spam模块: 1000

import spam money=1000 spam.change() # 调用模块里函数 print(spam.money) # 0
(3)模块另起别名:
作用:当模块名称比较长的时候,可以通过另起别名方便调用
例如:
import spam as SR print(SR.money) # 1000
(4)一次性导入多个模块
例如:
import os ,sys,time # PS:不推荐这样写
【4】
(1)模块导入方式二:
定义方式:from...impo...
例如:
from spam import read1
(2)
from...import... 与 import 区别
(1)在前者中以后调用的时候不需要再在加上模块名的前缀
(3)from...import ...优缺点
优点:调用更加方便
缺点:容易与本地存在的变量名产生冲突
例如:
from spam import read1 read1 = 'SR' print(read1) # SR
原因:
read1 = 'SR' from spam import read1 print(read1) # <function read1 at 0x00000000029E9A60>
PS:
(1)首先在执行文件内存空间中会包含一个read1的内存地址
(2)在调用模块里的read1 会将内存地址从原来指向SR改成指向模块里的代码
图解:
(4)from...import... *
作用:
(1)当模块中有太多名字需要被导入的时候可以一次性导入全部
(2)但是不推荐这样 虽然一次性有很多都需要导入 但是假如模块中很多名字还是不需要导入的 我们也将不需要导入的给导入了 浪费内存空间
例如:

from spam import * print(money) # 1000 print(read1) # <function read1 at 0x00000000021E9A60> print(read2) # <function read2 at 0x00000000021E9AE8> print(change) # <function read2 at 0x00000000021E9AE8>
PS:只是内部实验效果 假如真实环境中 模块有2000个名称需要被导入 但是模块总共有2w如果用该方法就会平白多匹配1w8的名称
(5)__all__:
作用:将需要被导入模块的名字假如列表中 通过该方法调用列表 即调用需要的模块
例如:

from spam import * print(money) # 1000 print(read1) # <function read1 at 0x00000000021E9A60> print(read2) # 报错 print(change) # 报错
(6)模块循环导入问题:
(1)程序设计不合理
(2)程序设计阶段应该避免
例如:

#m1.py print('正在导入m1') from m2 import y x='m1' #m2.py print('正在导入m2') from m1 import x y='m2' #run.py import m1 执行run.py会抛出异常 正在导入m1 正在导入m2 Traceback (most recent call last): File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/aa.py", line 1, in <module> import m1 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module> from m2 import y File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m2.py", line 2, in <module> from m1 import x ImportError: cannot import name 'x'
解释:
(1)首先run在调用m1之前会开辟一个名称空间
(2)执行m1的代码 首先打印正在导入m1 在调用m2开辟一个新的名称空间
(3)调用m2打印正在导入m2 然后执行导入的代码 但是这时候想m1取值 而m1本身内部没有值 故报错
(4)同理m1向m2中索值 但是m2中也不存在y 故报错
解决办法:
(1)将模块索取值放在导入模块之上
(2)当名称空间内部先有值
例如:

print('正在导入m1') x='m1' from m2 import y print('正在导入m2') y='m2' from m1 import x import m1
(7)py文件的区分:
(1)不同的人对不同的py文件有不同的定义
(2)当别人使用我们写的代码 但是自己本身代码在执行 对别人来说执行属于无用的
例如:

# 导入文件 def index(): print('index') def func(): print('func') index() func() # 执行文件 import md import md ''' index func PS:调用模块的执行结果 但是该结果对我无用 '''
解决办法:__name__
(1)当文件为执行文件的时候其打印结果为__main__
(2)当文件被当做模块导入的时候其打印结果为模块名称
# 模块 def index(): print('index') def func(): print('func') if __name__ == "__main__": index() func()
(7)模块的查找顺序
(1)内存
(2)内置空间
(3)sys.path:在该情况下,其将一堆文件组成一个列表 且第一个文件永远为执行文件当前文件夹
PS:如果想在sys.path添加文件路径可以通过append执行
(8)绝对导入相对导入
(1)绝对导入:
(1)以执行文件所在文件文件夹路径为准
(2)且无轮在执行文件还是导入文件都适用
(2)相对导入:
(1).代表当前所在路径
(2)..代表上一级文件所在路径
(3)相对导入不能再执行文件中使用
二:包#
(1)什么是包
定义:包就是一系列模块的结合体
基本概念:其实就是含有__init__的文件夹 主要就是用文件夹将一些模块打包组织一起
PS:
(1)在pyhton3中如果文件夹不含有__init__在调用的时候不会报错 而在python2中如果如果文件夹不含有__init__会报错
(2)包的目的不是为了执行 而是为了被使用
(2)使用包的好处
(1)随着功能越写越多代码组织结构不清晰 需要用多个文件夹存储不同的功能块
(2)用包将各个功能组织连接一起 提高代码的结构性 扩展性
(3)首次导入包过程
(1)首先执行文件产生一个名称空间
(2)包内部创建一个__init__的名称空间 然后执行包内部代码 将内部代码名称存入__init__的名称空间中
(3)执行文件获取到一个指向__init__名称空间的名字
(4)包的导入方式
方式一:import + 包名称
方式二:from...import...
(5)绝对导入 相对导入
绝对导入与相对导入 # 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入 # 优点: 执行文件与被导入的模块中都可以使用 # 缺点: 所有导入都是以sys.path为起始点,导入麻烦 # 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入 # 符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹 # 优点: 导入更加简单 # 缺点: 只能在导入包中的模块时才能使用 #注意: 1. 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内 2. attempted relative import beyond top-level package # 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!