模块(module)
模块module
从逻辑上说是一组功能的组合,本质上一个模块就是一个包含Python定义和声明的文件,文件名是模块名字加上.py
后缀。
模块可以包含可执行的语句和函数定义,这些语句的目的是为了初始化模块,它们只会在模块第一次遇到import
导入语句时才会执行。import
语句可以在程序中的任意位置使用,同一个模块会被import
导入多次时,为了防止重复导入,在第一次导入后就将模块名加载到内存了,后续import
语句仅仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句。
使用模块的好处可以大大提高代码的可维护性,其次编写代码也不必再从零开始。当一个模块编写完毕,可以被其它地方引用。使用模块还可以避免函数名和变量名冲突,相同名字的函数或变量完全可以分别存在不同的模块中。
模块导入(import)
模块搜索路径
import mod
当执行import
导入模块时解释器都在做什么呢?解释器是如下路径中搜索目标模块的:
- 在当前执行文件所在的文件夹中查找是否存在目标模块,若不存在则搜索失败。
- 在系统设置的
python
环境变量指定的路径中搜索 - 在python安装时指定的目录下搜索
查看导入模块时的搜索路径
$ python3
>>> import sys
>>> sys.path
[
'',
'D:\\python\\program\\python38\\python38.zip',
'D:\\python\\program\\python38\\DLLs',
'D:\\python\\program\\python38\\lib',
'D:\\python\\program\\python38',
'D:\\python\\program\\python38\\lib\\site-packages'
]
如需手工指定路径加入到模块搜索路径可使用
$ python3
>>> abspath = r"D:\\python\\module"
>>> sys.path.append(abspath)
>>> sys.path
模块导入流程
首先会找到需要导入的模块,判断当前模块是否已经被导入过,如果没有导入过则执行导入流程。
导入时先会创建一个属于当前模块的命名空间,如果用户没有定义变量来引用当前模块的内存地址的话,就会使用模块的名称来引用当前模块的内存地址。如果用户使用as
来指定变量接收内存地址,接着就会将内存地址赋值给指定变量,此时在后续下文调用时只能使用指定变量进行调用,不能再使用模块名称来调用,调用后执行模块中的代码。
如果模块已经被导入过,解释器不会重新执行模块内的语句,后续import
语句仅仅是对已经加载到内存中的模块对象增加一次引用。
模块导入顺序
多个模块导入时可使用逗号分隔,按照规范建议模块导入的顺序为:内置模块 > 第三方扩展模块 > 自定义模块
导入的模块与命名空间
导入的模块会重新开辟一块独立的名称空间,定义在此模块中的函数会把当前模块的命名空间当作全局命名空间,这样当前空间和模块运行空间也就分离开了,互不影响。
模块别名
模块在导入时开辟了新的空间内存,默认使用模块名称来引用新空间的内存地址,有时候模块名称会很长,执行调用模块中的功能时会显得不方便。为了更好地使用模块,可以为模块起别名。在导入模块时,为了不让模块使用默认的名字来引用内存空间,而是由自定义的变量来引用模块的内存地址。
例如:使用变量mn
作为模块的别名引用module
的引用内存地址
import module_name as mn
对模块指定功能的导入
from ... import
使用from...import
导入模块功能时,模块已经全部加载。
绝对导入
绝对导入要给出当前模块、函数的完整路径,import
语句使用点号作为分隔符来分隔包或模块。
import ecommerce.products
相对导入
在包存在的情况下如果已经知道父模块的名字可使用相对导入
from .database import Database
如何让Python文件即可以被当作模块来引用,也可以作为脚本来执行呢?
只需要在代码中添加__name__ == ' __main__'
判断条件,Python解释器即可知道条件内的为脚本执行的内容。
$ vim mod.py
# coding=UTF-8
list = [100, 200, 300]
str = "hello world"
def fn(x, y):
print('x = %s, y = %s' % (x, y))
class Klass:
pass
if (__name__ == "__main__"):
print(str)
print(list)
fn(0, 1)
obj = Klass()
print(obj)
模块组织(package)
Python中包package
的概念在模块module
之上,为了方便管理而将文件进行打包,打包目录下的第一个文件需要是__init__.py
,然后是模块和子目录。如果子目录下也存在__init__.py
文件则会作为当前包的子包。
引入包为了避免模块命名冲突,简单来说,Python为避免同名模块的问题,引入按文件目录来组织模块的方法,也就是包。
package
包是存放在文件夹中的模块集合,包名是文件夹的名字。如果需要告知Python当前文件夹是一个Python的包,需在当前文件夹下创建名为__init__.py
的文件。如果没有创建__init__.py
文件,就无法从当前文件夹下导入模块。
__init__.py
文件的作用
- Python中作为包的标识不能被删掉
- 可定义
__all__
用来模糊导入