Python游戏世界打怪升级之新手指引十五【模块、包】
模块、包
今天我们来学习一下Python里面的模块和包,在学习之前我们需要首先了解什么是模块,什么是包;下面可以看下它们的定义,
-
模块
- 模块是包含Python定义和语句的文件,文件名是py后缀
- 模块内部,通过全局变量
__name__,可以获得模块名
-
包
- 包是通过
包.模块名来构造的,也就是一个包可以包含多个模块 - 里面必须包含
__init__.py文件 - 使用包的好处就是不用担心不同包的作者的模块名一样导致冲突
- 包是通过
只看定义可能会很模糊,下面来举例,更加的形象生动
自定义模块
首先创建下面文件
fibo.py
# 斐波那契数列模块
def fib(n): # 打印斐波那契数列直到 n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # 返回斐波那契数列直到 n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
这个fibo.py就是一个模块,我们可以在CMD命令行中进行引入,从而使用
注意这个Import fibo,意思就是导入fibo这个模块,从而使用它里面的两个函数;后面讲导入的时候会详细说明
(.venv) PS D:\Code_Study\Python_world> python
Python 3.13.2 (tags/v3.13.2:4f8bb39, Feb 4 2025, 15:23:48) [MSC v.1942 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import fibo
>>> fibo.fib(10)
0 1 1 2 3 5 8
>>> fibo.fib2(10)
[0, 1, 1, 2, 3, 5, 8]
>>> fibo.__name__
'fibo'
>>> fib = fibo.fib
>>> fib2 = fibo.fib2
>>> fib(10)
0 1 1 2 3 5 8
>>> fib2(20)
[0, 1, 1, 2, 3, 5, 8, 13]
以脚本方式执行模块
我们可以在命令行中以python fibo.py <arg>脚本的形式运行模块
(.venv) PS D:\Code_Study\Python_world> python .\fibo.py 20
0 1 1 2 3 5 8 13
(.venv) PS D:\Code_Study\Python_world>
- 首先改造上面的fibo.py文件,发现最下面加入了
__name__==__main__的方法;它的作用就是和导入模块一样,但是会把__name__赋值为"__main__" - 添加的代码作用就是,导入sys模块,使用sys.argv[1]接受第一个变量,并且转为int类型,赋值给fib函数
- 改造后的文件现在既可以当作脚本,也可以用作一个可供导入的模块,因为解析命令行的代码只有在自己执行的时候,才起作用
- 被其他文件导入的时候,那两行代码就不起作用
# 斐波那契数列模块
def fib(n): # 打印斐波那契数列直到 n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
def fib2(n): # 返回斐波那契数列直到 n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a + b
return result
if __name__ == '__main__':
import sys
fib(int(sys.argv[1]))
除了上面自定义模块之外,Python还提供了一些标准模块供使用;
比如下面的dir()函数,可以查找模块定义的名称,结合上面的fibo.py模块进行使用;
返回结果是经过排序的字符串列表,这里除了会把函数、类、变量找出来
>>> import fibo
>>> dir(fibo)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fib', 'fib2']
可以私下自己去Python官网文档去查阅标准库
模块的搜索路径
Python如何查找模块?它会按照sys.path里面的路径进行顺序查找
- 当前目录
- 环境变量PYTHONPATH的目录
- Python标准库目录
- 第三方库目录
下面让我们看一下导入又是怎么回事
导入
上面创建了一个模块py文件,下面就可以进行模块的导入的;首先导入有以下几种方式
- import 模块名
- from 模块名 import 函数/类/变量
- from 模块名 import *
- import 模块名 as 别名;【注意:as也可以适用于上面的情况,但是不包括*的情况】
- 相对导入,这个放到包后面进行演示
下面让我们结合上面的py文件进行演示
fibo.py
# 斐波那契数列模块
def fib(n): # 打印斐波那契数列直到 n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # 返回斐波那契数列直到 n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
test_fibo.py
# 方法一,直接导入fibo模块
import fibo
if __name__ == '__main__':
fib = fibo.fib
fib2 = fibo.fib2
fib(10)
print(fib2(20))
# 方法二,从fibo模块导入具体函数(也可以是类、变量)
from fibo import fib, fib2
if __name__ == '__main__':
# fib = fibo.fib
# fib2 = fibo.fib2
fib(10)
print(fib2(20))
# 方法三,从fibo模块导入全部
from fibo import *
if __name__ == '__main__':
# fib = fibo.fib
# fib2 = fibo.fib2
fib(10)
print(fib2(20))
# 方法四,导入fibo模块并且使用别名fb
import fibo as fb
if __name__ == '__main__':
fib = fb.fib
fib2 = fb.fib2
fib(10)
print(fib2(20))
导入其实不复杂,重要的是掌握好模块与模块之间的路径,确保可以被找到就行
包
包的结构
注意,在使用包的时候,必须要创建一个__init__文件,里面可以没有内容,也可以执行包的初始化代码或设置 __all__ 变量
下面看实例,来自于Python官网文档
假设要为统一处理声音文件与声音数据设计一个模块集(“包”)
sound/ 最高层级的包
__init__.py 初始化 sound 包
formats/ 用于文件格式转换的子包
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ 用于音效的子包
__init__.py
echo.py
surround.py
reverse.py
...
filters/ 用于过滤器的子包
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
包的导入和使用
和模块的导入相比,其实就是前面加入了包名,具体看一下例子
import sound.effects.echo
作用就是导入sound下面的effects下面的echo模块,必须通过全名来引用
sound.effects.echo.xxxx(a,b,c,d)
from sound.effects import echo
作用就是从sound下面的effects下面导入echo模块,只需要使用echo就可以引用
echo.xxxx(a,b,c,d)
from sound.effects.echo import echofilter
作用就是从sound下面的effects下面的echo模块,导入echofilter函数、变量、类;可以直接引用
echofilter(a,b,c,d)
不建议从包中导入*
为什么不建议,可以看下下面的例子
from sound.effects import *
通过目录结构可以发现,effects下面有很多模块,使用的时候会造成浪费时间来查找自己所需要的模块
但是可以通过下面的方法进行解决,就是提供包的显示索引,也就是__init__文件里的__all__变量
运行 from package import * 时,它就是被导入的模块名列表。
__all__ = ["echo", "surround", "reverse"]
如果__init__文件里面定义了一个函数,和__all__变量里面的同名,那么这个就会被函数覆盖,不会被导入进去了
相对导入
这里需要参考上面的包结构,进行使用
- 一个点【.】表示当前目录
- 两个点【..】表示上一级目录
假设现在所在的文件是surround模块
from . import echo .表示当前目录
from .. import formats ..表示上一级目录的formats包
from ..filters import equalizer ..filters表示上一级目录的filters包下面的equalizer

浙公网安备 33010602011771号