【一】模块介绍
【1】什么是模块
- 在Python中,一个py文件就是一个模块,文件名为xxx.py模块名则是xxx,导入模块可以引用模块中已经写好的功能
- 使用模块既保证了代码的重用性,又增强了程序的结构性和可维护性
- 另外除了自定义模块外,我们还可以导入使用内置或第三方模块提供的现成功能
【2】模块的优点
- 极大地提高了程序员的开发效率。
【3】模块的来源
- 内置的:python解释器自带的,直接拿来使用的
- 第三方的:别人写的,如果想用,就要先下载在使用
- 自定义的:我们自己写的
【4】模块的存在形式
- 我们自己写的py文件(一个py文件就是一个模块)
- 包:一系列py文件的集合(文件夹)
- 一个包里面会有一个__init__.py文件
【二】模块的使用
【1】准备
- 新建文件foo.py
name = "ligo"
# 定义一个函数 函数的功能是打印name
def show_name():
print(name)
# 定义一个函数修改name
def change_name():
global name
name = 'scott'
print(name)
# 内嵌函数
def outer():
def inner():
print(f"这是 outer 内部 的 inner")
return inner()
【2】直接导入
#import语句
import py文件名/模块名
(1)import导入模块会发生哪些事
- 要想在另外一个 py 文件中引用foo.py中的功能
- 需要使用 import foo
- 首次导入模块会做三件事:
- 执行源文件代码
- 产生一个新的名称空间用于存放源文件执行过程中产生的名字
- 在当前执行文件所在的名称空间中得到一个名字 foo,该名字指向新创建的模块名称空间
- 若要引用模块名称空间中的名字,需要加上该前缀
import foo
#打印当前模块对象位置
print(foo) # <module 'foo' from'D:\\Python\\pythonProject\\pythonProject1\\bao\\foo.py'>
#打印模块中的name值
print(foo.name) # ligo
#调用修改全局变量name的函数,修改name的值
foo.change_name() # scott
#打印修改后的那么值
print(foo.name) # scott
#调用内嵌函数
func = foo.outer()
func() # 这是 outer 内部 的 inner
(2)import导入模块方式
#单独导入多个模块
import foo1
import foo2
import foo2
#一次性导入多个模块
import foo1,foo2,fool3
- 不同类别的导入顺序如下:
- python内置模块
- 第三方模块
- 程序员自定义模块
- 我们也可以在函数内导入模块,在文件开头导入模块属于全局作用域,在函数内导入的模块属于局部作用域
【3】详细导入
(1)语法
- from ... import ... 语句
from 模块位置 import 模块名
- 与import语句类似,不同的是在import中,引用模块中的名字时需要在名字前面加上foo.作为前缀,而from...import...语句可以直接引用模块中的名字
from foo import show_name,change_name,outer
show_name()
change_name()
outer()
#也可以指定想要的模块中的方法和参数
from foo import change_name
change_name()
(2)导入所有
#rom语句支持from foo import *语法, * 代表将foo中所有的名字都导入到当前位置
from foo import *
show_name()
change_name()
outer()
【4】重命名模块
- from ... import ... as ... 语句
from 模块位置 import 模块名 as 自定义名字
- 给导入的模块起一个别名
#为导入的模块foo在当前位置起别名f,以后再使用时就用这个别名f
import foo as foo_old
foo_old.show_name()
foo_old.change_name()
foo_old.outer()
#还可以为导入的一个名字起别名
from foo import show_name as get_name
get_name()
【三】循环导入问题
- 循环导入问题指的是在一个模块加载/导入的过程中导入另外一个模块,而在另外一个模块中又返回来导入第一个模块中的名字
- 由于第一个模块尚未加载完毕,所以引用失败、抛出异常
【1】循环导入问题的问题所在
- m1.py
print('正在导入m1')
from m2 import y
x='m1'
- m2.py
print('正在导入m2')
from m1 import x
y='m2'
- main.py
import m1
[1]问题一
- 执行mian.py会抛出异常
#正在导入m1
#正在导入m2
#ImportError: cannot import name 'x'
- 分析
- 先执行main.py--->执行import a
- 开始导入m1并运行其内部代码--->打印内容"正在导入m1"
- --->执行from m2 import y 开始导入m2并运行其内部代码--->打印内容“正在导入m2”
- --->执行from m1 import x,由于m1已经被导入过了,所以不会重新导入,所以直接去m1中拿x
- 然而x此时并没有存在于m1中,所以报错
[2]问题二
- 执行文件不等于导入文件,比如执行m1.py不等于导入了m
#直接执行m1.py抛出异常
#正在导入m1
#正在导入m2
#正在导入m1
#ImportError: cannot import name 'y'
- 分析
- 执行m1.py,打印“正在导入m1”,
- 执行from m2 import y
- 导入m2进而执行m2.py内部代码
- --->打印"正在导入m2"
- 执行from m1 import x
- 此时m1是第一次被导入
- 执行m1.py并不等于导入了m1
- 于是开始导入m1并执行其内部代码
- --->打印"正在导入m1"
- 执行from m1 import y
- 由于m1已经被导入过了
- 所以无需继续导入而直接问m2要y
- 然而y此时并没有存在于m2中所以报错
【2】问题的解决办法
[1]方法一
- 导入语句放到最后,保证在导入时,所有名字都已经加载过
- m1.py
print('正在导入m1')
x='m1'
from m2 import y
- m2.py
print('正在导入m2')
y='m2'
from m1 import x
- main.py
import m1
print(m1.x)
print(m1.y)
[2]方法二
- 导入语句放到函数中,只有在调用函数时才会执行其内部代码
- m1.py
print('正在导入m1')
def f1():
from m2 import y
print(x,y)
x = 'm1'
- m2.py
print('正在导入m2')
def f2():
from m1 import x
print(x,y)
y = 'm2'
- main.py
import m1
m1.f1()
【四】搜索模块的路径与优先级
【1】模块的分类
- 模块其实分为四个通用类别,分别是:
- 1、使用纯Python代码编写的py文件
- 2、包含一系列模块的包
- 3、使用C编写并链接到Python解释器中的内置模块
- 4、使用C或C++编译的扩展模块
- 加载顺序:使用C或C++编译的扩展模块 --> 使用C编写并链接到Python解释器中的内置模块 --> 包含一系列模块的包 --> 使用纯Python代码编写的py文件
- 在导入一个模块时
- 如果该模块已加载到内存中,则直接引用
- 否则会优先查找内置模块
- 然后按照从左到右的顺序依次检索 sys.path中定义的路径
- 直到找到模块对应的文件为止
- 否则抛出异常
【2】查看模块的搜索路径
#sys.path也被称为模块的搜索路径,它是一个列表类型
import sys
print(sys.path)
#['D:\\Python\\pythonProject\\pythonProject1',
# 'D:\\Python\\pythonProject\\pythonProject1',
# 'D:\\PyCharm 2023.3.5\\plugins\\python\\helpers\\pycharm_display',
# 'D:\\python310.zip',
# 'D:\\DLLs',
# 'D:\\lib',
# 'D:\\PyCharm 2023.3.5\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
#sys.path中的第一个路径通常为空,代表执行文件所在的路径,所以在被导入模块与执行文件在同一目录下时肯定是可以正常导入的
#针对被导入的模块与执行文件在不同路径下的情况
#为了确保模块对应的源文件仍可以被找到,需要将源文件 foo.py 所在的路径添加到 sys.path 中
#假设 foo.py 所在的路径为 /python/pythonProject/
import sys
# 也可以使用sys.path.insert(……)
sys.path.append(r'/python/pythonProject/')
# 无论foo.py在何处,我们都可以导入它了
import foo
【五】模块小结
【1】什么是模块
-
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀
-
import加载的模块分为四个通用类别:
-
使用python编写的代码(.py文件)
-
已被编译为共享库或DLL的C或C++扩展
-
包好一组模块的包
-
使用C编写并链接到python解释器的内置模块
-
【2】模块的介绍与使用(见上文)
【3】模块的优点
- 如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失
- 因此我们通常将程序写到文件中以便永久保存下来
- 需要时就通过python test.py方式去执行
- 此时test.py被称为脚本script。
- 随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。
- 这时我们不仅仅可以把这些文件当做脚本去执行
- 还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用
【六】包
【1】什么是包
- 包是一个模块的集合,能把多个模块的功能组合到一起,然后按照其功能和作用进行分类,利于用户的使用,包可以通过import语句来引入和使用
- Python的包分为标准库包和第三方库包:
- 标准库包是Python内置的包,包含了一些基本的模块和函数,如os、sys、random等
- 第三方库包是第三方开发的包,通常提供了更加丰富和高级的功能
【2】创建包
- 创建一个文件夹,这个文件夹的路径下必须要有一个名为__init__.py的文件,这个文件夹就是包
- 包是Python程序中用于组织模块的一种方式
- 在pycharm文件中新建Python软件包会自动创建 init.py 文件
【3】使用包
(1)语法
#【1】直接使用包
import 包名.包名.模块名
#【2】详细使用包
from 包名.模块名 import 模块中的方法
(2)使用
- add.py
def add(a, b):
print("这里是加法!")
return int(a) + int(b)
- reduce.py
def reduce(a, b):
print("这里是减法!")
return int(a) - int(b)
- main.py
#【1】直接使用包
import add
import reduce
print(add.add(6,4))
print(reduce.reduce(6,4))
# 这里是加法!
# 10
# 这里是减法!
# 2
#【2】详细使用包
from bao import add
from bao import reduce
print(add.add(6, 4))
print(reduce.reduce(6, 4))
# 这里是加法!
# 10
# 这里是减法!
# 2
【4】制作包
(1)注册包
- 在包下的
__init__.py
中注册相关变量 __init__.py
# 注意这里要用相对路径
# 从 add.py和reduce.py 中将需要导出的方法导入到这里
from .add import add
from .reduce import reduce
(2)使用包
# 将注册在 __init__.py 中的方法导入过来
from bao import add
from bao import reduce
# 使用包的模块的方法
print(add(6, 4)) # 这里的add是方法名
print(reduce(6, 4)) # 这里的reduce是方法名
# 这里是加法!
# 10
# 这里是减法!
# 2
【七】绝对路径和相对路径
【1】相对路径
- 相对路径是相对于当前工作目录或当前脚本文件所在目录的路径
# 加入文件所在路径是D:\Python\pythonProject\pythonProject1\01.text,那么相对路径就是:
path = '01.text'
path = './01.text' # ./表示当前同级目录下
path = '../01.text' # ../表示当前目录的上一级目录
#示例
with open(file='01.text',mode='r',encoding='utf8') as fp:
res = fp.read()
print(res)
【2】绝对路径
- 绝对路径是文件或目录在文件系统中的完整路径,不依赖于当前工作目录
#使用时要使用文件的完整路径
path = 'D:\Python\pythonProject\pythonProject1\01.text'
#示例
with open(file='D:\Python\pythonProject\pythonProject1\01.text',mode='r',encoding='utf8') as fp:
res = fp.read()
print(res)
标签:name,Python,py,高级,导入,m1,模块,import
From: https://www.cnblogs.com/ligo6/p/18180001