day18 课程(模块 & 导入模块 & 制作模块 & 模块定位顺序 & all列表 & 包 & 制作包 & 导入包)
课程:https://www.bilibili.com/video/BV1o4411M71o?spm_id_from=333.788.videopod.episodes&p=333
18.1 了解模块
18.1.1 目标
了解模块
导入模块
制作模块
__all__
包的使用方法
18.1.2 模块
Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和 Python 语句
模块能定义函数、类和变量,模块里也能包含可执行的代码
18.2 导入模块之方法一
18.2.1 语法
# 1.导入模块 import 模块名 # 推荐 import 模块名1, 模块名2, ... # 不推荐 # 2.调用功能 模块名.功能名()
18.2.2 体验
# 1 导入模块 import math # 2 调用模块内的功能 print(math.sqrt(9)) # sqrt 开平方, 相除无论是整数还是浮点数, 最后都得浮点数 3.0 print(6 / 2) # 举例: 两个整数最后得浮点数 3.0 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Microsoft\WindowsApps\python3.13.exe D:\Pycharm\code\day18\01.模块的使用方法.py 3.0 3.0 Process finished with exit code 0
18.3 导入模块之方法二
18.3.1 语法
from 模块名 import 功能1, 功能2, 功能3, ...
18.3.2 体验
# 1 导入模块中的功能名字 from math import sqrt # 2 调用模块内的功能 print(sqrt(100)) # 不用写模块名, 直接调用功能即可 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Microsoft\WindowsApps\python3.13.exe D:\Pycharm\code\day18\01.模块的使用方法.py 10.0 Process finished with exit code 0
18.4 导入模块之方法三
18.4.1 语法
from 模块名 import *
18.4.2 体验
# 1 导入模块中的所有功能 from math import * # 2 调用模块内的功能 print(sqrt(100)) # 不用写模块名, 直接调用功能即可 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Microsoft\WindowsApps\python3.13.exe D:\Pycharm\code\day18\01.模块的使用方法.py 10.0 Process finished with exit code 0
18.5 定义别名
18.5.1 语法
注意:定义别名以后,只能使用别名,不能使用原模块名或功能名
# 模块定义别名 import 模块名 as 别名 # 功能定义别名 from 模块名 import 功能 as 别名
18.5.2 体验
# 1 模块别名 import time as te te.sleep(3) print("hello world") # 2 功能别名 from time import sleep as sp sp(3) print("hello python") ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\02.定义别名.py hello world hello python Process finished with exit code 0
18.6 了解制作模块
在 Python 中,每个 Python文件都可以作为一个模块,模块的名字就是文件的名字,也就是说 自定义模块名必须要符合标识符命名规则
用作:简化代码量,可以拿来即用
18.7 制作模块之定义模块
新建一个 Python 文件,命名为 my_module.py ,并定义 test 函数
# 定义函数、形参、返回值 def test(A, B): print(A + B)
18.8 制作模块之测试和调用模块
18.8.1 测试模块
在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,开发人员会自行在 py文件中添加一些测试信息,例如:在 my_module1.py 文件中添加测试代码
# 定义函数、形参、返回值 def testA(A, B): print(A + B) # 先在本模块中测试, 其他文件调用此模块时, 导入所有代码会把测试代码也调用一遍, 影响结果 testA(1, 2) # 测试后这个测试内容怎么办? ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\my_module.py 3 Process finished with exit code 0
18.8.2 调用模块
# 调用模块 import my_module # 调用模块中的功能 my_module.testA(1,6) # 返回 7 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\03.调用制作的模块.py 3 # 这里 3 是测试时的调用,影响其他模块的调用结果 7 Process finished with exit code 0
注意:返回 3 是 my_module 原文件整个被调用到其他文件中,影响调用文件的输出结果
18.8.3 测试模块仅本地调用
注意:,在开发过程中,文件被频繁的修改,测试,删除和注释也会浪费大量时间,如何解决?
此时,无论是当前文件还是其他已经导入该模块的文件,在运行的时候都会自动执行 test函数 的调用
# 定义函数、形参、返回值 def testA(A, B): print(A + B) # 先在本模块中测试, 其他文件调用此模块时, 导入所有代码会把测试代码也调用一遍, 影响结果 # testA(1, 2) # 测试后这个测试内容怎么办? print(__name__) # __name__ 是模块内置的变量, 如果运行的本模块, 则为 __main__ ,其他模块调用则会打印此模块名称 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\my_module.py __main__ # 本模块自己调用返回 __main__ Process finished with exit code 0
# 调用模块 import my_module # 调用模块中的功能 my_module.testA(1,6) # 返回 7 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\03.调用制作的模块.py my_module # 其他模块调用返回原模块名称 7 Process finished with exit code 0
由此,解决办法如下:
# 定义函数、形参、返回值 def testA(A, B): print(A + B) # 先在本模块中测试, 其他文件调用此模块时, 导入所有代码会把测试代码也调用一遍, 影响结果 # testA(1, 2) # 测试后这个测试内容怎么办? # 只在当前文件中调用该函数, 其他导入的文件内不符合该条件, 则不执行 test函数 调用 if __name__ == '__main__': # __name__ 是模块内置的变量, 如果运行的此模块, 则为 __main__ ,其他模块调用则会打印此模块名称 testA(1,2) # 本模块自己测试时使用, 不会影响其他模块调用输出的结果 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\my_module.py 3 Process finished with exit code 0
其他文件调用此模块
# 调用模块 import my_module # 调用模块中的功能 my_module.testA(1,6) # 返回 7, 测试的函数不会执行, 不会干扰模块调用 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\03.调用制作的模块.py 7 Process finished with exit code 0
18.9 了解模块定位顺序
当导入一个模块,Python 解释器对模块位置的搜索顺序是:由近及远
1.当前目录
2.如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 的每个目录
3.如果都找不到,Python 会查看默认路径,例如:UNIX 下,默认路径一般为 /usr/local/lib/python/
模块搜索路径存储在 sys模块 的 sys.path 变量中,变量里包含当前目录,PYTHONPATH 和由安装过程决定的默认目录
import sys print(sys.path)
注意点:
1.自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
2.使用 from 模块名 import 功能 的时候,如果功能名字重复,调用到的是最后定义或导入的功能
18.10 模块定位顺序之注意点1
默认情况下:
import random num = random.randint(1, 5) print(num) # 出现 1-5 的随机数 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\05.模块定位顺序之注意点1.py 4 Process finished with exit code 0
当在同一目录下创建一个 random 的文件,里面是空内容,模块名重复,导致模块无法使用
import sys # 强制从缓存中移除 random 模块 if 'random' in sys.modules: del sys.modules['random'] import random num = random.randint(1, 5) # 因为有同名 random 模块, randint有黄色下划线, 警告没有 randint 方法 print(num) # 上面报错,导入了同一目录下 random模块,没有 randint 方法 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\05.模块定位顺序之注意点1.py Traceback (most recent call last): File "D:\Pycharm\code\day18\05.模块定位顺序之注意点1.py", line 11, in <module> num = random.randint(1, 5) # 因为有同名 random 模块, randint有黄色下划线, 警告没有 AttributeError: module 'random' has no attribute 'randint' Process finished with exit code 1
18.11 模块定位顺序之注意点2
默认情况下:
from time import sleep print("A") sleep(2) # 休眠了2秒后, 输出下面内容 print("B") ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\06.模块定位顺序之注意点2.py A B Process finished with exit code 0
当在同一文件中导入相同名字的功能,功能名字重复,后导入的生效
from time import sleep def sleep(): print('自定义sleep函数') print("A") sleep(2) # 报错: 函数未定义参数 TypeError: sleep() takes 0 positional arguments but 1 was given 说明使用的是 自己定义的sleep 函数 print("B") ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\06.模块定位顺序之注意点2.py Traceback (most recent call last): File "D:\Pycharm\code\day18\06.模块定位顺序之注意点2.py", line 9, in <module> sleep(2) # 休眠了2秒后, 输出下面内容 TypeError: sleep() takes 0 positional arguments but 1 was given A Process finished with exit code 1
相同的代码,当顺序发生变化
def sleep(): print('自定义sleep函数') from time import sleep print("A") sleep(2) # 休眠了2秒后, 输出下面内容 说明使用的是 time 模块中的 sleep 功能 print("B") ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\06.模块定位顺序之注意点2.py A B Process finished with exit code 0
18.12 扩展:名字重复的严重性
注意:import 模块名 多个后,即使功能名相同,但使用方式是 模块名.功能名 ,模块名不同,所以也不用担心功能重复
import time # 导入模块 print(time) # 打印模块 module time time = 1 # 声明变量 print(time) # 返回 1 当声明变量与导入模块名相同, 后导入的生效, 覆盖前面 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\07.扩展:名字重复的严重性.py <module 'time' (built-in)> 1 Process finished with exit code 0
问题:为什么变量也能覆盖模块?
答:在 Python 中,数据是通过 引用 传递的,因此要注意名字重复的严重性
18.13 __all__ 列表
如果一个模块文件中有 __all__ 变量,当使用 from xxx import * 导入时,只能导入这个列表中的元素
my_module1 模块代码
__all__ = ['testA'] # 列表中只放了 testA def testA(): # testA 函数 print('testA') def testB(): # testB 函数 print('testB')
导入模块的文件代码
from my_module1 import * testA() # 返回 testA testB() # 报错 NameError 因为 my_module1模块, 控制了只有 all列表 里面的功能才能导入 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe "D:\Pycharm\code\day18\08.__all__ 列表.py" testA Traceback (most recent call last): File "D:\Pycharm\code\day18\08.__all__ 列表.py", line 6, in <module> testB() NameError: name 'testB' is not defined Process finished with exit code 1
18.14 了解包
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为 __init__.py 文件,这个文件称为包(即一个文件夹下多个模块的整合,只要找到这个包,即能使用包下所有模块的功能)
18.15 制作包
[New] -> [Python Package] -> 输入包名 -> [OK] -> 新建功能模块(有联系的模块)
注意:新建包后,包内部会自动创建 __init__.py 文件,这个文件控制着包的导入行为
18.15.1 创建包
1.新建包 mypackage
2.新建包内模块: my_module1 和 my_module2
3.模块内代码如下
# my_module1 print(1) def info_print1(): print('my_module1')
# my_module2 print(2) def info_print2(): print('my_module2')
18.16 导入包之方法一
18.16.1 导入1
import 包名.模块名 # 导入 包名.模块名.功能名 # 使用
18.16.2 体验
import mypakcage.my_module1 # 导入 包名 模块名 mypakcage.my_module1.info_print1() # 使用 包名 模块名 功能名 ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\09.导入包之方法一.py 1 my_module1 Process finished with exit code 0
18.17 导入包之方法二
注意:必须在 __init__.py 文件中添加 __all__ = [] ,控制允许导入的模块列表
18.17.1 导入2
from 包名 import * # 导入 模块名.功能名 # 使用
18.17.2 体验
# __init__.py 文件 __all__ = ['my_module2']
from mypakcage import * # 导入 包名 my_module2.info_print2() # 可以使用 使用 模块名 功能名 my_module1.info_print1() # 无法使用 没在 __init__.py 文件中 __all__列表 定义, 无法使用 报错:NameError ------------------------------------------------ 执行后 C:\Users\马俊南\AppData\Local\Programs\Python\Python37\python.exe D:\Pycharm\code\day18\10.导入包之方法二.py Traceback (most recent call last): File "D:\Pycharm\code\day18\10.导入包之方法二.py", line 5, in <module> my_module1.info_print1() NameError: name 'my_module1' is not defined 2 my_module2 Process finished with exit code 1
18.18 模块和包的总结
1.导入模块方法
import 模块名 from 模块名 import 功能 from 模块名 import *
注意:as 别名 对模块或功能重命名,调用时使用别名
2.创建包
[New] -> [Python Package] -> 输入包名 -> [OK] -> 新建功能模块(有联系的模块)
3.导入包
import 包名.模块名 from 包名 impoort * # __init__.py 文件中需要定义 __all__ =[]
注意:__all__ = [] :允许导入的模块或功能列表
———————————————————————————————————————————————————————————————————————————
无敌小马爱学习
浙公网安备 33010602011771号