在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。

为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就可以称之为一个模块(Module)。

模块和包的定义

在Python中一般对文件和文件的称呼(很多开发者的平时开发中也有人都称为模块)

  • 一个py文件,模块(module)。
  • 含多个py文件的文件夹,包(package)。

注意:在包(文件夹)中有一个默认内容为空的__init__.py的文件,一般用于描述当前包的信息(在导入他下面的模块时,也会自动加载)。

  • py2必须有,如果没有导入包就会失败。
  • py3可有可无。

使用模块有什么好处

  1. 最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。

  2. 使用模块还可以避免函数名和变量名冲突。每个模块有独立的命名空间,因此相同名字的函数和变量完全可以分别存在不同的模块中,所以,我们自己在编写模块时,不必考虑名字会与其他模块冲突

模块导入&调用

查找路径

当定义好一个模块或包之后,如果想要使用其中定义的功能,必须要先导入,然后再能使用。
导入,其实就是将模块或包加载的内存中,以后再去内存中去拿就行。

关于导如时的路径:

在Python内部默认设置了一些路径,导入模块或包时,都会按照指定顺序逐一去特定的路径查找。

  1. import sys
  2. print(sys.path)
  1. ['当前执行脚本所在的目录',
  2. 'D:\\Anaconda3\\python36.zip',
  3. 'D:\\Anaconda3\\DLLs',
  4. 'D:\\Anaconda3\\lib',
  5. 'D:\\Anaconda3',
  6. 'D:\\Anaconda3\\lib\\site-packages',
  7. 'D:\\Anaconda3\\lib\\site-packages\\win32',
  8. 'D:\\Anaconda3\\lib\\site-packages\\win32\\lib',
  9. 'D:\\Anaconda3\\lib\\site-packages\\Pythonwin']

说明:

  • 这里我使用的Anaconda,sys.path在不同的安装路径和Python版本下可能有所不同
  • 如果使用的是Pycharm,会把当前项目目录加入 sys.path,但是代码运行时是没有Pycharm的,因此不要考虑这个路径

想要导入任意的模块和包,都必须写在如下路径下,才能被找到。
也可以自动手动在sys.path中添加指定路径,然后再导入可以,例如:

  1. import sys
  2. sys.path.append("路径A")
  3. import xxxxx # 导入路径A下的一个xxxxx.py文件

模块加载流程

被导入的模块文件.py 全部执行一遍,if __name__ == "__main__": 部分不会被执行
如果模块已经被导入在内存中,不会被再次导入

三种导入

import导入

import应用场景:项目根目录的包、模块级别的导入。

注解:单层的模块、单层包下的模块

  1. # many.py
  2. def show():
  3. pass
  4. def hide():
  5. pass

image.png

  1. # 导入一个模块
  2. import many # many输入项目根目录下的模块
  3. v1 = many.show()
  4. import commons.page as pg # commons输入项目根目录下的包
  5. v2 = pg.pagination()
  6. # 导入一个包
  7. import commons
  8. print(commons.VERSION) # 导入的包可以直接调用该包下面__init__.py文件的变量
  9. # 多层包下的模块无法导入
  10. # import commons.tencent.wechat

from导入

from比import更强大,可以导入嵌套的包、模块、成员

嵌套的包wechat
image.png

  1. # 导入成员
  2. from many import show, hide
  3. from commons.utils import encrypt
  4. v1 = encrypt("ecithy")
  5. print(v1)
  6. # 导入一个模块(至少一个嵌套)
  7. from commons import utils
  8. utils.encrypt("xxx")
  9. utils.f1()
  10. # 导入一个包(至少一个嵌套)
  11. from commons import tencent

如果要调用多层嵌套包下的模块,import 前必须要是当前模块的直接上级包
因为在调用时不能 包名.模块,只能模块.成员

  1. from commons.tencent import wechat
  2. from commons.tencent.wechat import yue

相对导入

相对导入只能在包中进行
image.png

导入别名

如果项目中导入 成员/模块/包 有重名,那么后导入的会覆盖之前导入,为了避免这种情况的发生,Python支持重命名,即:

  1. from xxx.xxx import xx as xo
  2. import x1.x2 as pg

除此之外,有了as的存在,让 import xx.xxx.xxxx.xxx 在调用执行时,会更加简单(不常用,了解即可)。

  • 原来 ```python import commons.page

v1 = commons.page.pagination()

  1. - 现在
  2. ```python
  3. import commons.page as pg
  4. v1 = pg.pagination()

name

执行一个py文件时

  1. __name__ = "__main__"

导入一个py文件时

  1. __name__ = "模块名"

主文件,其实就是在程序执行的入口文件,例如: