1、包的使用
前面我们已经介绍了,Python模块是一个以“.py”结尾的Python文件,每个模块里面可以定义函数,类,变量和可执行的代码等。在程序开发中,随着功能越来越多,我们无法将所有功能都放到一个文件中,于是我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性,Python为我们提供了一种把模块组织到一起的方法,即创建一个包。包就是一个含有_init_.py文件的文件夹,文件夹内可以组织子模块或子包,例如
test.py
Packages/ #顶级包
├── __init__.py
├── funs1.py
├── funs2.py
└── Packages2/ #子包
├── __init__.py
├── funs3.py
└── funs4.py
通俗来讲,包的本质就是一个文件夹,文件夹唯一的功能就是将模块文件组织起来,但该文件夹下必须存在“_init_.py”文件,“_init_.py”文件的内容可以为空。“_init_.py”文件用于标识当前文件夹是一个包。例如:我们创建一个Packages文件夹,并且在Packages目录下创建“_init_.py”文件,内容如下:
_init_.py:
if __name__ == '__main__':
print("作为主程序运行")
else:
print("Packages初始化")
接着在Packages目录下创建“funs1.py”和“funs2.py”文件,内容如下:
funs1.py:
def print1():
print("这是funs1模块")
funs2.py:
def print2():
print("这是funs2模块")
最后我们在Packages同级目录下(注意:不是在Packages文件夹内)创建“test.py”文件来调用“Packages”包,例如
动手练一练: test.py:
from Packages.funs1 import print1
from Packages.funs2 import print2
print1()
print2()
执行以上代码,输出结果为:
Packages初始化
这是funs1模块
这是funs2模块
上面的例子中可以看出,导入包的过程会默认执行“_init_.py”的内容,并且“_init_.py”内容可以为空。简单来说,包是一个包含多个模块的目录,它可以有一个特殊的_init_.py文件来初始化包,以及控制包的导入行为。通过使用包,我们可以将代码组织得更有条理,更方便其他开发人员的使用。
2、包的相对导入和绝对导入
绝对导入和相对导入是Python中用于导入模块的两种不同方式。
包的绝对导入是指完整的包路径,从顶层的包开始,一级一级到达需要导入的模块。
包的相对导入是指从当前位置开始的导入路径。“.”代表当前文件所在的目录,“..”代表当前目录的上一级目录,依此类推。
例如,假设有以下目录结构:
test.py
Packages/ #顶级包
├── __init__.py
├── funs1.py
├── funs2.py
├── Packages2/ #子包
│ ├── __init__.py
│ ├── funs3.py
│ └── funs4.py
└── Packages3/ #子包
├── __init__.py
├── funs5.py
└── funs6.py
在test.py中,如果想导入funs3.py,绝对导入语句如下:
from Packages.Packages2 import funs3
在funs1.py中,如果想导入同一子包下funs2.py模块中的print2()函数,可以使用相对导入语句如下:
from .funs2 import print2
在funs5.py中,如果想导入上级包中的“funs3”模块,也可以使用相对导入语句如下:
from ..Packages2 import funs3
针对包内部模块之间的相互导入推荐使用绝对导入。相对导入一般用在大型复杂的程序中。此外,如果你的代码中没有正确使用带有“.”或者“..”的相对导入时,Python解释器容易抛出一个导入错误:ImportError: attempted relative import with no known parent package。
3、使用“from...import *”导入
在使用包时同样支持“from...import *”导入,毫无疑问“*”代表的是所有的名字。例如:我们更改一下test.py文件,内容如下:
动手练一练: test.py:
from Packages.funs1 import *
from Packages.funs2 import *
print1()
print2()
执行以上代码,输出结果为:
Packages初始化
这是funs1模块
这是funs2模块
上面的例子中可以看出,“*”可以把一个模块的所有内容全都导入到当前的程序中。大部分情况下我们的Python程序不应该使用这种导入方式,因为使用“*”时,你不知道导入什么名字,很有可能会覆盖掉你之前已经定义的名字,所以这种方法不该被过多地使用。
4、使用“import...as”导入
“import...as”是用于引入一个模块的同时为该模块取一个别名,使用语法:“import A as B”,表示引入“A”模块并取别名为“B”,在该文件的后续调用中“B”就相当于是“A”。在Python中,如果import的语句比较长,导致后续引用不方便,就可以使用as语法,例如:我们更改一下test.py文件,内容如下:
动手练一练: test.py:
import Packages.funs1 as p1
import Packages.funs2 as p2
p1.print1()
p2.print2()
也可以改写如下:
from Packages.funs1 import print1 as p1
from Packages.funs2 import print2 as p2
p1()
p2()
执行以上代码,输出结果为:
Packages初始化
这是funs1模块
这是funs2模块
上面的两个例子输出的结果一模一样,使用“import...as”方法后可以直接通过“p1”“p2”调用,方便我们书写代码。