0%
Theme NexT works best with JavaScript enabled
内容概要
内容详细 包介绍 1 2 3 4 5 6 7 8 9 10 11 随着模块数目的增多,把所有模块不加区分地放到一起也是极不合理的 于是python为我们提供了一种把模块组织到一起的方法 ---> 创建一个包 包就是一个含有__init__.py文件的文件夹,文件夹内可以组织子模块或自包 例:↓↓↓ pool/ ├── __init__.py ├── futures │ ├── __init__.py │ ├── process.py │ └── thread.py └── versions.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 需要强调的是 接下来我们就以包pool为例来介绍包的使用,包内各文件内容如下 class ProcessPoolExecutor : def __init__ (self,max_workers ): self.max_workers=max_workers def submit (self ): print ('ProcessPool submit' ) class ThreadPoolExecutor : def __init__ (self, max_workers ): self.max_workers = max_workers def submit (self ): print ('ThreadPool submit' ) def check (): print ('check versions’) # __init__.py文件内容均为空
包的使用 导入包与init.py 1 2 3 4 5 6 7 8 9 10 11 12 13 包属于模块的一种,因而包以及包内模块均是用来被导入使用的,而绝非被直接执行,首次导入包,同样会做三件事: 1 执行包下的__init__.py文件2 产生一个新的名称空间用于存放__init__.py执行过程中产生的名字3 在当前执行文件所在的名称空间中得到一个名字pool,该名字指向__init__.py的名称空间,例如http://pool.xxx和pool.yyy中的xxx和yyy都是来自于pool下的__init__.py,也就是说导入包时并不会导入包下所有的子模块与子包 import poolpool.versions.check() pool.futures.process.ProcessPoolExecutor(3 ) pool.versions.check()要求pool下有名字versions,进而pool.versions下有名字check。pool.versions下已经有名字check了,所以问题出在pool下没有名字versions,这就需要在pool下的__init__.py中导入模块versions
1 2 3 4 5 6 7 8 9 强调 1. 关于包相关的导入语句也分为import 和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如import 顶级包.子包.子模块,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。2 、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间3 、import 导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
绝对导入与相对导入 1 2 3 4 5 6 针对包内的模块之间互相导入,导入的方式有两种 1 、绝对导入:以顶级包为起始from pool import versions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 、相对导入:.代表当前文件所在的目录,..代表当前目录的上一级目录,依此类推from . import versions同理,针对pool.futures.process.ProcessPoolExecutor(3 ),则需要 from . import futures from . import process 在包内使用相对导入还可以跨目录导入模块,比如thread.py中想引用versions.py的名字check import 也能使用绝对导入,导入过程中同样会依次执行包下的__init__.py,只是基于import 导入的结果,使用时必须加上该前缀
1 2 3 4 5 6 7 例1 : import pool.futures pool.futures.xxx
1 2 3 4 5 6 7 8 9 10 例2 : import pool.futures.thread thread_pool=pool.futures.thread.ThreadPoolExecutor(3 ) thread_pool.submit() 相对导入只能用from module import symbol的形式,import ..versions语法是不对的,且symbol只能是一个明确的名字 from pool import futures.process from pool.futures import process
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 针对包内部模块之间的相互导入推荐使用相对导入,需要特别强调: 1 、相对导入只能在包内部使用,用相对导入不同目录下的模块是非法的2 、无论是import 还是from -import ,但凡是在导入时带点的,点的左边必须是包,否则语法错误总结包的使用需要牢记三点: 1 、导包就是在导包下__init__.py文件2 、包内部的导入应该使用相对导入,相对导入也只能在包内部使用,而且...取上一级不能出包3 、 使用语句中的点代表的是访问属性m.n.x ----> 向m要n,向n要x 而导入语句中的点代表的是路径分隔符import a.b.c --> a/b/c,文件夹下a下有子文件夹b,文件夹b下有子文件或文件夹c 所以导入语句中点的左边必须是一个包
from 包 import * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 在使用包时同样支持from pool.futures import * ,毫无疑问*代表的是futures下__init__.py中所有的名字,通用是用变量__all__来控制*代表的意思 __all__=['process' ,'thread' ] 最后说明一点,包内部的目录结构通常是包的开发者为了方便自己管理和维护代码而创建的,这种目录结构对包的使用者往往是无用的,此时通过操作__init__.py可以“隐藏”包内部的目录结构,降低使用难度,比如想要让使用者直接使用 import poolpool.check() pool.ProcessPoolExecutor(3 ) pool.ThreadPoolExecutor(3 ) 需要操作pool下的__init__.py from .versions import checkfrom .futures.process import ProcessPoolExecutorfrom .futures.thread import ThreadPoolExecutor