模块与包
1. 模块
在 python 中一个 .py
,文件就是一个模块,模块名就是文件名不要后缀
,导入模块就可以引入模块中已经写好的功能,这样做的好处就是,后期维护起来更方便
,程序结构更加清晰
,python中模块可以分为 python内置模块
,第三放模块
,自定义模块
,
1.1 导入模块
导入模块的方式有很多
import 模块名
: 使用时需要带上模块名,声明是使用该模块的名称
from 模块名 import 功能名
: 使用时不需要带上模块名,容易与当前名称空间中的名字起冲突,当前名称空间存在相同的名字
,则后定义的名字会覆盖之前定义的名字
from 模块名 import *
: 表示将当前模块名所有的名字都导入到当前位置,不推荐
from 模块名 import 功能名 as 别名
: 导入的名字过长时采用起别名来精简代码
另外为被导入的名字起别名也可以很好的避免与当前名字发生冲突
,可以保证调用方式的一致性
,
导入内置模块
import math
print(math.sqrt(9)) # 3.0
导入自定义模块foo.py
x=1
def get():
print(x)
def change():
global x x=0
class Foo:
def func(self):
print('from the func')
在另一个文件引入这个模块,会执行原文件代码
,产生一个新的名称空间
用于存放源文件
执行过程中产生的名字
,当前执行文件所在的名称空间得到一个名字foo
,该名字指向新创建的的模块和名称空间
,若要引用模块名称空间中的名字,需要加上前缀
# 导入模块foo
import foo
# 引用模块foo中变量x的值赋值给当前名称空间中的名字a
a=foo.x
# 调用模块foo的get函数
foo.get()
# 调用模块foo中的change函数
foo.change()
# 使用模块foo的类Foo来实例化,进一步可以执行obj.func()
obj=foo.Foo()
加上foo.
作为前缀就相当于说明要引用foo
名称空间中的名字,所以肯定不会与当前执行文件所在名称空间中的名字相冲突
1.2 导入模块顺序
- python内置模块
- 第三方模块
- 自定义模块
1.3 __all__
如果一个模块文件中有__all__
变量,当使用from xxx import *
导入时,只能导入这个列表中的元素。
my_module模块代码
__all__ = ['func']
def func():
print('func')
def bar():
print('bar')
导入模块的文件代码
from my_module1 import *
func() # 可用
bar() # 不可用,抛异常
在模块导入中我们需要注意循环导入问题
,同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,即便是该模块尚未加载完毕也不会执行内部代码
,在一个模块加载/导入的过程中导入另一个模块
,而在另一个模块中又返回导入第一个模块中的名字
,由于第一个模块尚未加载完毕
,所以引用失败,抛出异常,
解决方法
方式一:导入语句放到最后,保证在导入时,所有名字都已经加载过
,
方式二:导入语句放到函数中,只有在调用函数时才会执行其内部代码
2. 包
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py
文件,那么这个文件夹就称之为包。包属于模块的一种
,因而包以及包内模块君是用来被导入的,
pool/ #顶级包
├── __init__.py
├── futures #子包
│ ├── __init__.py
│ ├── process.py
│ └── thread.py
└── versions.py #子模块
2.1 绝对导入和相对导入
绝对导入
以顶级包开始,相对导入
代表当前文件所在的目录,.
代表当前文件的路径绝对导入
# pool下的__init__.py
from pool import versions
相对导入
#pool下的__init__.py
from . import versions
相对导入只能在包内部使用
,用相对导入不同目录下的模块事非法的
无论是import
还是form-import
,但凡是导入是带有节点的,点左边必须是包,否则语法报错
2.3 __all__
在使用包时同样支持from pool.fultures import *
,毫无疑问*
就是代表fultures.__init__.py
中所有的名字,通过用变量__all__
来控制*
代表的意思
此时通过操作__init__.py
,可以隐藏
包内部的目录结构,降低使用难度,比如想让使用者直接使用
#futures下的__init__.py
__all__=['process','thread']
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。