Modules
同大多数其他编程语言一样,python提供了将较大圆吗文件分割为多个较小文件,并在运行时将他们链接起来的机制。
每个较小的文件都可以称作是一个module
,在运行时,这些module
被定位、编译并最终生成module
的对象,这是一个自包含的变量包,构成了namespace
。
在python中,module
是被import
链接起来的,之后import
通过search path
去定位各个module
文件。一些C程序员喜欢将python的module import
操作和C #include进行比较,但是这并不合适。在python中,import
并不是仅仅将文件以文本的形式插入另一文件,而是一个运行时操作,包括三个步骤:
- 找到文件
- 将其编译成byte code
- 运行module的代码以构建其定义的对象
import
会从5个目录搜索module
文件,按照优先顺序:
- 程序的
home
目录 - 环境变量
PYTHONPATH
所指示的目录 - python标准库目录
-
.pth
文件的内容 - 第三方库的
site-package home
目录
可以通过系统变量sys.path
查询这些目录。
import
找到module
文件后,对其进行编译,生成可用的module
对象。所有在module
的顶层定义的变量都可以被外部调用,也就是会成为module
对象attributes
。
Packages
import
不仅可以命名module
,还可以命名包含module
的目录的路径。一个包含了module
的目录就是一个package
,也就是说import
可以导入package
。一个package import
将你电脑上的目录转换成了另一种namespace
,这样,attributes
来自于子目录和包含在目录中的module
文件。在python3.x中,import
有3种形式:
- Basic modules。
import
从sys.path
内的每个路径中查找这些module
文件。 - 如果一个
sys.path
内的路径中存放的是一个目录,这个目录中包含一个名为__init__.py
的特殊文件,那么这个目录将被当作一个package
处理。也就是可以通过import A.B.C
的形式引入package
,以及package
中的module
。 - 在同一个
package
中,普通的import
和from
语句用sys.path
的查找规则查找其他package
中的module
。而“from . import A”的形式,意味着import
仅从package
内部查找目标module
。注意,python2.X的规则稍有不同,普通的(非“from . import A”的形式)import
仍然会优先搜索当前的package
目录。
namespace package
在python3.X中,对package
进一步增强,引入了namespace package
。namespace package
同一般的package
并没有本质的区别,他只是创建package
的另一种方式。
-
namespace package
中没有__init__.py
文件。 -
namespace package
可以跨多个目录
namespace package的import算法如下:
- 如果发现了目录\子目录_init_.py,那么将
import
进来一个一般的package
并返回。 - 如果发现了目录\子目录\module.{py,pyc,或者其他类型的module扩展},那么导入一个module,并返回,
- 如果发现了目录\子目录,那么将其记录下来并继续扫描查找路径中下一个目录。
- 如果1和2都没能返回任何的
module
或者package
,而这时如果第三步中记录了至少一个目录,那么就可以为其创建一个namespace package
。
结语
Module
和package
的引入,极大的增强了python的功能:
- 提高了代码的重用性。
- 划分了namespace,减少了变量名的冲突。
- 实现了服务或者数据的分享。
网友评论