设为首页 加入收藏

TOP

python进阶(28)import导入机制原理(一)
2023-07-25 21:25:23 】 浏览:60
Tags:python 进阶 import

前言

在Python中,一个.py文件代表一个Module。在Module中可以是任何的符合Python文件格式的Python脚本。了解Module导入机制大有用处。
 

1. Module组成

一个.py文件就是一个module。Module中包括attribute, function等。 这里说的attribute其实是module的global variable。
我们创建1个test1.py文件,代码如下

# 定义1个全局变量a
a = 1
# 声明一个全局变量moduleName
global moduleName


# 定义一个函数printModuleName
def printModuleName():
    print(a + 2)
    print(__name__)
    print(moduleName)

print(dir())

这里我们定义了3个全局变量amoduleNameprintModuleName,除了我们自己定义的以外还有module内置的全局变量
 

1.1 Module 内置全局变量

上面我们说到了,每一个模块都有内置的全局变量,我们可以使用dir()函数,用于查看模块内容,例如上面的例子中,使用dir()查看结果如下:

['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'moduleName', 'printModuleName']

其中a, moduleName, printModuleName 是由用户自定义的。其他的全是内置的。下面介绍几个常用的内置全局变量
 

1.1.1 __name__

指的是当前模块的名称,比如上面的test1.py,模块的名称默认就是test1,如果一个module是程序的入口,那么__name__=__'main'__,这也是我们经常看到用到的
 

1.1.2 __builtins__

它就是内置模块builtins的引用。可以通过如下代码测试:

import builtins
print(builtins == __builtins__)

打印结果为True,在Python代码里,不需要我们导入就能直接使用的函数、类等,都是在这个内置模块里的。例如:rangedir
 

1.1.3 __doc__

它就是module的文档说明,具体是文件头之后、代码(包含import)之前的第一个多行注释,测试如下

点击查看代码
"""
模块导入机制测试
"""


import builtins


# 定义1个全局变量a
a = 1
# 声明一个全局变量moduleName
global moduleName


# 定义一个函数printModuleName
def printModuleName():
    print(a + 2)
    print(__name__)
    print(moduleName)


print(__doc__)

最后打印结果为

模块导入机制测试

当然如果你想查看某个方法的说明,也可以这么使用

 

1.1.4 __file__

当前module所在的文件的绝对路径
 

1.1.5 __package__

当前module所在的包名。如果没有,为None。
 

2. 包package

??为避免模块名冲突,Python引入了按目录组织模块的方法,称之为包(package)。包是含有Python模块的文件夹。

??当一个文件夹下有init.py时,意为该文件夹是一个包(package),其下的多个模块(module)构成一个整体,而这些模块(module)都可通过同一个包(package)导入其他代码中。

??其中init.py文件用于组织包(package),方便管理各个模块之间的引用、控制着包的导入行为。

??该文件可以什么内容都不写,即为空文件,存在即可,相当于一个标记。

??但若想使用from pacakge_1 import *这种形式的写法,需在init.py中加上:__all__ = ['file_a', 'file_b'] ,并且package_1下有file_a.pyfile_b.py,在导入时init.py文件将被执行。

??但不建议在init.py中写模块,以保证该文件简单。不过可在init.py导入我们需要的模块,以便避免一个个导入、方便使用。

??其中,__all__是一个重要的变量,用来指定此包(package)被import *时,哪些模块(module)会被import进【当前作用域中】。不在__all__列表中的模块不会被其他程序引用。可以重写__all__,如__all__= ['当前所属包模块1名字', '模块1名字'],如果写了这个,则会按列表中的模块名进行导入

??在模糊导入时,形如from package import *,*是由__all__定义的。

??当我们在导入一个包(package)时(会先加载__init__.py定义的引入模块,然后再运行其他代码),实际上是导入的它的__init__.py文件(导入时,该文件自动运行,助我们一下导入该包中的多个模块)。我们可以在 init.py中再导入其他的包(package)或模块或自定义类。
 

2.1 实战案例

首先我们创建3个包,分别是testtest2test3
test包下创建test1.py用来执行测试
test2包下创建file_a.pyfile_b.py,用来测试包的导入
test3包下创建file_c.py,辅助测试
具体结构如下:

核心代码在test2/__init__.py中如下

__all__ = ['file_a', 'file_b', 'file_c', 'test_d']


from test3 import file_c


def test_d():
    return "test_d"

解释下,当我们在test/test1.py中写了from test2 import *这句代码,程序不是直接导入test2下的所有模块,而是导入__init__.py文件并自动运行,由于我们写了__all__ = ['file_a', 'file_b', 'file_c', 'test_d'],file_a和file_b是当下包中的模块,file_c是我们从test3包中导入的,test_d是__init__.py下我们定义的函数。

所以from test2 import *就是把__all__中指定的模块和函数导入进来了,接着我们查看test1.py下的代码

from test2 import *
print(file_a.a())
print(file_b.b())
print(file_c.c())
print(test_d())

如果打印有结果,则证明了导入成功,并且导入的是__all__下的模块和函数
 

3.sys.modules、命名空间

 

3.1 sys.modules

s

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python基础之网络编程:7、网络并.. 下一篇python中的字符串操作

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目