无论我们选择用何种语言进行程序设计时,都不可能只有一个文件(除了“hello world”),通常情况下,我们都需要在一个文件中调用另外一个文件的函数呀数据等等,总之要操作其他文件中的代码,在Java中,只要在同一个文件目录下,我们就不需要通过import导入,但是在Python中,我们就需要通过import来进行导入,这样我们才能应用其他文件中定义的函数和数据等代码。
下面就以两个文件为例,例如我们有 a.py 和 b.py 两个文件,当我们需要在 b.py 文件中应用 a.py 中的 func( ) 函数时,应该如何做呢,有两种情况,分别为在同一文件目录下和不在同一目录下。
假设我们的模块包的目录结构如下:
.
└── ab
│── a.py
└── b.py
在b.py文件中用下面两种方法即可完成对a.py文件中func( )函数的调用:
① 第一种方法是直接引用模块,之后想引用该模块中的函数时需要加上模块名的前缀。
import a #引用模块
a.func( )
② 第二种方法是引用模块中的函数,这样之后调用该函数时就不需要再加上模块名的前缀了。
import a #应用模块
from a import func #引用模块中的函数
func() #这里调用函数就不需要加上模块名的前缀了
①若不在同一目录,但在同一个模块包(module package)中,假设我们的模块包的目录结构如下:
.
└── ab
├── aa
│ ├── a.py
└── bb.py
在b.py文件中,我们使用最直接的导入方式来调用a.py文件中的func( )函数,这里有四种调用方式:
from aa import a
from a import func #引用模块中的函数
或者
from aa.a import a
或者
import aa.a
或者
import aa.a as w
②若不在同一目录,python查找不到,必须进行查找路径的设置,将模块所在的文件夹加入系统查找路径
import sys
sys.path.append(‘a.py所在的路径’)
import a
a.func()
然后对工程模块目录中经常出现的 "init.py"文件 进行介绍。
经常在python的模块目录中会看到 “init.py” 这个文件,如果你是使用python的相关IDE来进行开发,那么如果目录中存在该文件,该目录就会被识别为 module package 。也就是说 “init.py” 文件的作用是标识该目录是一个python的模块包(module package),此外该文件还可用于配置模块的初始化操作,并简化模块的导入操作
假设我们的模块包的目录结构如下:
.
└── mypackage
├── subpackage_1
│ ├── test11.py
│ └── test12.py
├── subpackage_2
│ ├── test21.py
│ └── test22.py
└── subpackage_3
├── test31.py
└── test32.py
如果我们使用最直接的导入方式,将整个文件拷贝到工程目录下,然后直接导入:
from mypackage.subpackage_1 import test11
from mypackage.subpackage_1 import test12
from mypackage.subpackage_2 import test21
from mypackage.subpackage_2 import test22
from mypackage.subpackage_3 import test31
from mypackage.subpackage_3 import test32
这个例子里面文件比较少,如果模块比较大,目录比较深的话,可能自己都记不清该如何导入。(很有可能,哪怕只想导入一个模块都要在目录中找很久)。在这种情况下,init.py 就很有作用了。
如果目录中包含了 init.py 文件,比如下图:
.
└── mypackage
├── __init__.py
├── subpackage_1
│ ├── test11.py
│ └── test12.py
├── subpackage_2
│ ├── test21.py
│ └── test22.py
└── subpackage_3
├── test31.py
└── test32.py
当用 import 导入该目录模块包(package)时,会执行 init.py 里面的代码。也就是说,init.py 在包被导入时会被执行。
所以,我们可以在__init__.py 中指定默认需要导入的模块,从而简化模块导入操作,比如加入下面的语句:
from mypackage.subpackage_1 import test11
from mypackage.subpackage_1 import test12
from mypackage.subpackage_2 import test21
from mypackage.subpackage_2 import test22
from mypackage.subpackage_3 import test31
from mypackage.subpackage_3 import test32
这样后续我们就可以利用__init__.py进行模块导入了,仅使用下面的一条导入语句就可以代替之前的一大串导入语句。
import mypackage as pak
需要注意的是,在我们执行import时,当前目录是不会变的(就算是执行子目录的文件),还是需要完整的包名mypackage.subpackage_1
,而不可以直接写成subpackage_1
。
有时候我们在做导入时会偷懒,将包中的所有内容导入
from mypackage import *
这是怎么实现的呢? all 变量就是干这个工作的。
all 关联了一个模块列表,当执行 from xx import * 时,就会导入列表中的模块。比如我们将 init.py 修改为:
__all__ = ['subpackage_1', 'subpackage_2']
列表中没有包含 subpackage_3,因此当执行from mypackage import *
语句时,就等价于执行from mypackage import subpackage_1, subpackage_2
语句。
需要注意的是,导入操作会继续查找 subpackage_1 和 subpackage_2 中的__init__.py 并执行。(但是此时不会执行 import *)
在了解了 init.py 的工作原理后,可以知道该文件就是一个正常的用于放入初始化的python代码文件,同时可以简化模块的导入操作。