0
点赞
收藏
分享

微信扫一扫

Python零基础入门-6 模块和包


6.模块和包

模块modules

在之前的程序里,你可能用过类似​​from math import pi​​的语句来导入变量或函数。这其实就是在使用模块

模块:Python将程序存入一个文件,可在解释器中运行。这个文件就是模块

模块中的语句可以导入(import)到其他Python程序中。

使用模块的好处:模块化,每个模块写相关的功能;避免文件过长和混乱。

创建模块

新建一个文件(文件名为​​模块名.py​​),在文件里写程序。

举个例子:创建一个和三角形相关的模块:

新建文件​​tri_f.py​​,然后在里面写入:

import math

print("tri_f 模块 开始")

def edge_length(a, b, c):
"""返回三边长度之和"""
return a + b + c

def area(a, b, c):
"""返回三角形面积"""
p = (a + b + c) / 2
s = math.sqrt(p * (p - a) * (p - b) * (p - c))
return s

print("tri_f 模块 结束")

然后保存(Ctrl+s)。这样模块就创建好了。

使用模块

使用模块通过​​import​​语句导入模块中的变量定义、函数等可执行语句等。

例,使用模块​​tri.f​​。

在​​tri_f.py​同级目录下创建​​test.py​​。

注意:如果不是同级目录,解释器会找不到,需要在sys.path中添加查找路径,如

​import sys sys.path.append(r'D:\PY_TEST\pythonProject\6modules')​​ #替换为自己的目录

a, b, c = 3, 4, 5
# 从模块导入特定函数
from tri_f import area # 从tri_f模块导入函数area的定义
print(area(a, b, c)) # 然后就可以使用函数area,计算三角形面积了

# 导入模块
import tri_f #导入 tri_f模块
print(tri_f.area(a, b, c)) # 函数前面需要加上模块名

# 给模块起别名
import tri_f as tr
print(tr.area(a, b, c))

# (不推荐)从模块导入全部函数(_开头的函数除外)
from tri_f import *
print(area(a, b, c))
print(edge_length(a, b, c))

运行test.py我们得到下面结果:

tri_f 模块 开始
tri_f 模块 结束
6.0
6.0
6.0
6.0
12.0

通过import模块 ,我们不仅导入了函数,还会执行模块中的语句。

总结一下,Import的用法:

# 从模块导入特定函数
from 模块 import 函数

# 导入模块
import 模块

# 给模块起别名
import 模块 as 别名

# (不推荐)从模块导入全部函数(_开头的函数除外)及变量
from 模块 import *

模块名​​__name__​

你可能看到过 下面的语句:

 if __name__ == '__main__':
print('hello')

这里的​​__name__​​​实际上就是模块的名字。模块被导入时,​​__name__​​​是模块的文件名。当这个模块作为主程序运行时,模块的​​__name__​​​会赋值为​​'__main__'​​。

import math
print('name=',__name__)

def edge_length(a, b, c):
"""返回三边长度之和"""
return a + b + c

def area(a, b, c):
"""返回三角形面积"""
p = (a + b + c) / 2
s = math.sqrt(p * (p - a) * (p - b) * (p - c))
return s

if __name__ == '__main__':
print(area(3, 4, 5))
print('hello')

运行tri_f.py,输出:

name= __main__
6.0
hello

运行test.py时,tri_f中的​​__name__​​​就会变成模块名 ​​tri_f​​,所以不会执行tri.f模块中if里的内容:

if __name__ == '__main__':
print(area(3, 4, 5))
print('hello')

模块详情

import语句导入模块时发生的事情:

执行模块中语句(包括定义函数等)。

注意:

!模块中的语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行(防止重复)。

!需要注意,如果有多个相同函数名,最后定义的函数会把之前的同名函数覆盖掉。

!可以用与访问模块函数一样的标记法,访问模块的全局变量,​​modname.itemname​​。

模块有自己的私有符号表,用作模块中所有函数全局符号表。因此,模块内全局变量不会与用户定义的全局变量发生冲突。(别纠结,命名空间在第九章类会详细说)

包package

创建包

包是装着模块的文件夹,文件夹下必须含 ​​__init__.py​​ 文件。

最简情况下,​​__init__.py​​​ 只是一个空文件,但该文件也可以执行包的初始化代码,或设置 ​​__all__​​ 变量,详见下文(从包中导入*)。

sound/                          #顶层包
__init__.py #初始化
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.echofilter(input, output, delay=0.7, atten=4)​

  • (推荐)另一种导入子模块的方法是:

​from sound.effects import echo​

这段代码还可以加载子模块 ​​echo​​ ,不加包前缀也可以使用:

​echo.echofilter(input, output, delay=0.7, atten=4)​

  • Import 语句的另一种变体是直接导入所需的函数或变量:

​from sound.effects.echo import echofilter​

同样,这样也会加载子模块 ​​echo​​​,但可以直接使用函数 ​​echofilter()​​:

​echofilter(input, output, delay=0.7, atten=4)​

注意,使用 ​​from package import item​​ 时,item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。

优先查找包中定义的函数、类或变量等,未找到则假定 item 是模块,并尝试加载模块。如果仍然找不到 item,则触发 ​​ImportError​​ 异常。

相反,使用 ​​import item.subitem.subsubitem​​ 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。

从包中导入 *

类似模块导入*,使用 ​​from sound.effects import *​​​ 时,该语句应该导入包的所有子模块。但是这可能会导入太多东西, 浪费时间且造成冲突。因此,使用 ​​from sound.effects import *​​​只会导入在​​__init__.py​​​中​​__all__​​变量里的模块。

__all__ = ["echo", "surround", "reverse"]

相对导入

包中含有多个子包时还可以用 import 语句的 ​​from module import name​​​ 形式执行相对导入。这些导入语句使用前导句点表示相对导入中的当前包和父包。例如,相对于 ​​effect​​​包下的​​surround​​ 模块,可以使用:

from . import echo
from .. import formats
from ..filters import equalizer


举报

相关推荐

0 条评论