python AI技术教程之模块
模块的概念
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。
使用模块有什么好处?
最大的好处是大大提高了代码的可维护性。
其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。
你也许还想到,如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。
举个例子,一个abc.py的文件就是一个名字叫abc的模块,一个xyz.py的文件就是一个名字叫xyz的模块。
现在,假设我们的abc和xyz这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突。方法是选择一个顶层包名,比如mycompany,按照如下目录存放:
mycompany
├─ __init__.py
├─ abc.py
└─ xyz.py
引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz。
请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。
类似的,可以有多级目录,组成多级层次的包结构。比如如下的目录结构:
mycompany
├─ web
│ ├─ __init__.py
│ ├─ utils.py
│ └─ www.py
├─ __init__.py
├─ abc.py
└─ utils.py
文件www.py的模块名就是mycompany.web.www,两个文件utils.py的模块名分别是mycompany.utils和mycompany.web.utils。
特别注意
自己创建模块时要注意命名,不能和Python自带的模块名称冲突。例如,系统自带了sys模块,自己的模块就不可命名为sys.py,否则将无法导入系统自带的sys模块。
mycompany.web也是一个模块,请指出该模块对应的.py文件。
小结
模块是一组Python代码的集合,可以使用其他模块,也可以被其他模块使用。
创建自己的模块时,要注意:
- 模块名要遵循Python变量命名规范,不要使用中文、特殊字符;
- 模块名不要和系统模块名冲突,最好先查看系统是否已存在该模块,检查方法是在Python交互环境执行
import abc,若成功则说明系统存在此模块。
模块的使用
在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一下Python中的模块。
说的通俗点:模块就好比是工具箱,要想使用这个工具箱中的工具(就好比函数),就需要导入这个模块。
1.import
在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入。
形如:
import os => os.py
import time => time.py
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
在调用math模块中的函数时,必须这样引用:
模块名.函数名
这种方式必须加上模块名调用,因为可能存在这样一种情况:在多个模块中含有相同名称的函数,此时如果只是通过函数名来调用,解释器无法知道到底要调用哪个函数。所以如果像上述这样引入模块的时候,调用函数必须加上模块名。
在python中,模块通常可以分为两大类:内置模块(目前使用的)和自定义模块。
2.模块的导入方式
import 模块名
import 模块名 as 别名
from 模块名 import * # 代表导入这个模块所有的函数,可以直接通过函数名 调用函数
from 模块名 import 函数名 # 代表只导入这个函数名
3.as别名的使用
import random as rand # 将random取别名为rand
print(rand.randint(1,4)) # 通过别名来使用函数
4.time模块
"""
time.time(): 获取当前时间,返回的是一个数字
time.sleep(秒数): 休眠
"""
import time
star = time.time() # 程序开始的时间
list = []
for i in range(100000):
list.append(i)
end = time.time() # 程序结束的时间
print(f'程序运行的时间为{star - end}s时间')
#定位模块
当你导入一个模块,Python解析器对模块位置的搜索顺序是:
1.当前目录
2.如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
3.如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
4.模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录.
5.自定义模块
模块可以包含:全局变量、函数和类
# 创建一个自定义文件,如my_module1
def sum_num(num1, num2):
return num1 + num2
在其他文件中导入自定义模块:
import my_module1
# 调用自定义模块中的函数
my_module1.sum_num(10, 20)
测试模块:
在编写完自定义模块后,最好在自定义模块中对代码进行测试,以免出现任何异常。
升级
__name__的使用
print(__name__)
if __name__ == '__main__':
print('模块内部的测试')
调用者
import mycalc
print(mycalc.jia(2,38))
包的基础
2.1 什么是包?
包是一种包含多个模块的目录,它必须包含一个特殊的__init__.py文件(Python 3.3+中也可以是命名空间包,不需要__init__.py)。包可以嵌套,形成多层次的包结构。
2.2 包的结构
一个典型的包结构如下:
2.3 __init__.py文件的作用
__init__.py文件有以下作用:
1.标识目录为Python包
2.初始化包级别的代码
3.定义__all__变量,控制from package import *的行为
4.导入子模块或子包,使它们更容易访问
# bank_system/accounts/__init__.py
from .base import BankAccount
from .savings import SavingsAccount
from .checking import CheckingAccount
__all__ = ['BankAccount', 'SavingsAccount', 'CheckingAccount']
导入机制深入
3.1 模块搜索路径
当导入一个模块时,Python解释器按照以下顺序搜索:
1.内置模块(如sys、math等)
2.当前目录
3.环境变量PYTHON PATH指定的目录
4.标准库目录
5.第三方库目录(如site-packages)
可以通过sys.path查看搜索路径:
import sys
print(sys.path)
3.2 最佳实践
3.2.1 模块设计原则
- 单一职责原则:每个模块应该只负责一个明确的功能
- 高内聚低耦合:模块内部元素紧密相关,模块之间依赖最小化
- 清晰的接口:模块应该提供清晰、稳定的API
- 适当的抽象:隐藏实现细节,暴露必要的接口
3.2.2 包组织建议
- 按功能而非类型组织代码
- 保持包的扁平结构,避免过深的嵌套
- 使用__init__.py简化导入
- 为常用功能提供快捷方式
3.2.3 导入风格指南
- 标准库导入
- 第三方库导入
- 本地应用/库导入
- 每组导入之间空一行
- 点赞
- 收藏
- 关注作者
评论(0)