包的介绍

随着模块的数量增加,把所有的模块不加区分的放到一起是极不合理的一种做法,于是Python为我们提供了,把一些模块集中放到一起,成为一个模块的方法,那就是包,包就是一个文件夹,且这个文件夹含有__init__.py文件。文件夹内可以是子模块或者子包。

例如如下树形结构:

pool/                #顶级包
├── __init__.py     
├── futures          #子包
│   ├── __init__.py
│   ├── process.py
│   └── thread.py
└── versions.py      #子模块

强调:

# 1、在Python3中一个包下可以没有__init__.py文件,import导入的时候,也可以正常导入,不会报错,但是Python2的包下必须存在__init__.py,或者就会报错。

# 2、建立包的目的不是为了运行,而是被导入使用,其实包也是一种模块。只不过它是一堆模块的集合。

包的导入发生了什么事?

import pool # 导入包

'''

1、产生名称空间
2、运行包下的__init__.py文件,将运行过程中产生的名字都存放到1产生的名称空间中。
3、在当前执行文件的名称空间中拿到一个名字,即pool,该名称指向1的名称空间
'''

包的使用

我们常见一个文件夹名为pool,此时pool就是我们的包名,而pool文件夹下有如下文件:

  • __init__.py 包内置文件
  • m1.py 模块m1
  • m2.py 模块m2
  • m3.py 模块m3

包插图

__init_.py文件默认为空,我们添加如下内容:

print('我是__init__.py文件输出的内容')
# 模块的使用者: x1ong

import pool

运行x1ong.py之后得到如下结果:

包插图1

可以看到,我们导入包pool的时候,自动运行了pool下的__init__.py文件。

正因为在import pool的时候,会自动运行__init__.py文件,所以我们可以在该文件夹中调用包的其他模块。

绝对导入和相对导入

针对包内其他互相导入有两种导入方式:一种是相对导入,一种是绝对导入

绝对导入

1、以顶级包为起始

# pool下的__init__.py文件

from pool import m1  # 导入pool包下的m1模块
from pool.m1 import f1  # 导入pool包下的m1模块中的f1名字

绝对导入的应用

有一个名为pool的包,该包下面有三个模块和一个__init__.py文件,三个模块分别为m1和m2以及m3模块。

包插图2

m1.py的内容:

def f1():
	print('我是f1函数输出的内容>>>>')

m2.py的内容:

def f2():
	print('我是f2函数输出的内容>>>>')

m3.py的内容

def f3():
	print('我是f3函数输出的内容>>>>')

__init__.py的内容:

# 在__init__.py中导入包的其他模块中的名字
from pool.m1 import f1
from pool.m2 import f2
from pool.m3 import f3

而我们正常的执行文件为x1ong.py,我们在x1ong.py中导入pool包,要求该文件可以调用pool包中的所有模块对应的f1、f2、f3函数。

x1ong.pypool包的文件关系为

包插图3

x1ong.py的文件内容为:

import pool

print(pool.f1) # <function f1 at 0x7fada017e2f0>
print(pool.f2) # <function f2 at 0x7fada017e840>
print(pool.f3) # <function f3 at 0x7fada017e8c8>

可以正常访问。

相对路径

相对路径:.表示当前文件夹 ..表示上一层文件夹

相对路径的应用场景

常用于包内模块与包内模块之间的导入或者会报错。

# 1、相对导入只能在包内部使用,用相对导入不同目录下的模块是非法的

# 2、无论是import还是from-import,但凡是在导入时带点的,点的左边必须是包,否则语法错误

假设有如下应用场景:

包插图4

pool包下有一个sub_pool子包,而子包中__init__.pysub.py两个文件。

__init__.py的内容为:

print('我是sub_pool包下的__init__.py文件输出的内容')

sub.py的内容为:

def test():
	print('我是sub_pool包下的sub.py模块的内容')

使用相对路径,我们想要在x1ong.py中导入pool就可以访问到sub_pool子包下的sub模块下的test函数。该如何去做?

首先观察一下这个文件结构:

包插图5

可以发现sub_pool和pool包下的__init__.py文件是处在同一级。而我们导入pool包的时候,又自动会指定该包下的__init__.py文件,那么我们就可以在pool包下的__init__.py中导入sub_pool下的sub模块即可。

为pool下的__init__.py文件添加如下内容:

# .表示当前目录即pool目录下的sub_pool之后又通过.连接为sub_pool下的sub模块,再import导入sub模块下的test

from .sub_pool.sub import test 

那么我们在x1ong.py中,这样导入即可。

import pool

print(pool.f1)
print(pool.f2)

# 调用pool包下的sub子包下的test()方法
pool.test()
# import也能使用绝对导入,导入过程中同样会依次执行包下的__init__.py,只是基于import导入的结果,使用时必须加上该前缀

本文作者: x1ong
免责声明:本博客所有文章仅用于学习交流
转载声明:文章为作者原创文章 转载请注明来源
本文链接: https://www.giaoblog.com/python/23767.html
上一篇
下一篇