什么是模块?

模块,是一个以 .py 结尾的 Python 文件,该文件是一个集所有功能类似、或已封装好的代码集合。

模块内可以定义函数、类和变量,模块里也能包含可执行的代码。

使用模块文件来组织代码,可以使程序逻辑更清晰、更好用、更易读懂。

举个例子:

在当前项目下,新建一个 py_module.py 的文件,在文件中添加以下代码:

def show( val ):
   print("这是模块中定义的内容:" ,val)
   return None

以上的 py_module.py 就是一个简易的 Python 模块文件。

导入模块

模块在定义好之后,我们需要怎样去调用这个模块来使用呢?这时候就可以使用 import 关键字来引入模块文件了。

Python 提供以下 4 种方法将模块导入:

import ...    # 方法一
import ... as ...    # 方法二
form ... import ...    # 方法三
form ... import *    # 方法四
调用 Python 自带的模块,同样是使用上述方法。

import ... 语句

基本语法:

import module1[, module2[,... moduleN]

说明:

  • 一个 import 可以同时导入多个 模块,各模块之间使用半角逗号隔开即可。
  • 调用 模块 中的文件前,必须先 导入(import) 该模块文件, 一般都在程序的开始处执行导入(import)。
  • 一个模块只会程序被导入一次,不管执行了多少次 import 都是一样。
  • import ... 这种导入方法,在调用模块内定义的变量或函数等内容时,需要使用【模块.函数/变量】的方式来访问(例如:test.name)。

实例如下:

接着上面实例,在同一个项目中新建一个 test.py 的文件,然后输入以下内容:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import py_module   # 引入模块

py_module.show("hello world!")      # 调用模块中的 show 函数

输出结果:

这是模块中定义的内容: hello world!

import ... as ... 语句

import ... as ... 语句:用于变更模块的引用名称,该语句的好处在于 避免长名称的模块的在写程序时书写的累赘。

实例如下:

#!/usr/bin/python 
# -*- coding: UTF-8 -*-

# 引入 py_module 文件并重命名为 pm
import py_module as pm

# 调用模块中的函数时,使用变更后的名称
pm.show("hello world!")

实例输出:

这是模块中定义的内容: hello world!

form ... import... 语句

该语句的作用是从指定的模块中导入指定的部分,将该部分复内容制到当前命名空间(模块)中。语法如下:

from module_name import name1[, name2[, ... nameN]] 

说明:
这种导入方式不会把 引用模块 中的所有内容导入到 当前模块,而仅是将指定的内容导入到当前模块中。
这种导入方式在调用对应的内容(如:函数或属性)时,不需使用模块名( test.name),直接操作对象即可(如:name )。

实例演示:

#!/usr/bin/python 
# -*- coding: UTF-8 -*-

# 引入 py_module 模块中的 show 函数
from py_module import show

# 直接调用函数
show("hello world!")

这种导入方式不会把 py_module 模块中的所有内容导入到当前模块,而仅是将指定的 show() 这个函数导入到当前模块中。

form ... import * 语句

该语句会将指定引入的模块中的所有内容复制到当前命名空间(模块)中开来。该引入方式不推荐被过多的使用。

实例演示:

一次性引入 os 模块中所有可用内容。

from os import *

此中方式与 form ... import ... 类似,直接使用目标名称即可调用,而无需加入模块名进行调用。

【拓展:导入限制】

如果希望被导入模块允许(不允许)目标文件创建相同变量,可以在定义模块变量时做以下操作:
a ) 限制导入: 变量前加下划线 如: _y 或 _z=128
b ) 允许导入: 被导入模块中创建 all 声明 如: all = ['a', 'b', 'c']

在模块中,使用这种方式来定义变量后。在后面执行 from ... import * 语句时,程序会根据模块内变量定义的情况,自动执行导入或不导入操作。

查询已载入模块

使用 sys.modules 命令可以查看当前已加载的module名称和实例,具体如下:

import sys   # 先导入 sys 模块

sys.modules    # 查询当前模块已加载的module名称和实例

查询模块内容

使用 dir() 函数,可以查看指定模块中的内容,其函数以列表的形式返回结果,其内容包含定义的函数、变量等信息。例如:

dir(sys)   # 查看 sys 模块中的定义的内容

注意:该模块必须已经导入到当前操作环境中。

删除已引入模块

使用 del 语句可以删除指定的、已引入的模块。例如:

del sys   # 删除 sys 模块

注意:该语句只是删除了指定的名称,而不是删除名称应用的对象。

命名空间&作用域

在 Python 的模块中,所有定义的变量、函数等,其命名空间和作用域仅对当前模块有用(即所有的限制都已模块为分界点)。

在模块中定义了变量、函数等,其 命名空间 仅对当前模块有效(同样可以区分全局命名和局部命名空间),跨越模块则失效。

在模块中定义了变量、函数等,其 作用域 只作用于当前模块内(当然变量还是可以区分全局变量和局部变量的),跨越模块同样失效。

当需要在函数内变更一个全局的变量时,这时可以调用前使用 global 关键字声明即可!

实例 1:

效果: 测试模块中,在函数内如何调用全局的变量。
说明:在当前工程文件夹下创建一个名为 test_1.py 的文件,并输入一下内容:

#!/usr/bin/python 
# -*- coding: UTF-8 -*-

score = 100      # 定义一个全局变量 score

def student_score():
    global score      # 声明在该函数内使用的是全局变量的 score
    print('函数内调用 score 变量,值为:', score )
    score = 88  # 修改全局变量 score 的值
    print('函数内修改 score 变量后,值为 :', score )

# 调用函数
student_score()

实例输出:

函数内调用 score 变量,值为: 100
函数内修改 score 变量后,值为 : 88

分析:在函数内需要调用一个全局的变量时,只需使用 global 关键字在一开始处声明即可,接下来该函数内所调用的都是该全局变量的值(注意:在 global 的前面不能定义有与接下来 global 声明时所同样的变量,否则会报错)。

实例 2:

效果:查看 变量的命名空间和作用域的界限。
声明:
1、删除当前工程 test_1.py 文件内的 函数调用语句(即:student_score())。
2、同样使用当前工程文件,并新建一个名为 test_2.py 的文件,输入以下内容:

#!/usr/bin/python 
# -*- coding: UTF-8 -*-

import test_1    # 导入 test_1 模块

score = 23     # 在当前模块重新定义一个新的 score 变量

print('这是test_2.py文件中的 score值:', score)    # 验证 score 是使用了当前模块的值还是test_1.py文件中定义的值
test_1.student_score()   # 调用函数

实例输出:

这是test_2.py文件中的 score值: 23
函数内调用 score 变量,值为: 100
函数内修改 score 变量后,值为 : 88

分析:可见在 test_2.py 文件中,使用了与 test_1.py 文件中相同的变量名,且 test_2.py文件也导入了其 test_1.py 文件的内容,但是在调用变量的时候,程序却没有报错,而且在输出其值的时候,发现 score 变量使用的是 test_2.py 文件中定义的值。由此可推断出Python中变量的命名空间和作用域都是基于模块文件进行区分(分隔)的。

globals() 和 locals() 函数

根据调用地方的不同,globals()locals() 函数可被用来返回全局和局部命名空间里的名字。

如果在函数内部调用 locals(),返回的是所有能在该函数里访问的命名。

如果在函数内部调用 globals(),返回的是所有在该函数里能访问的全局名字。

两个函数的返回类型都是字典,所以可用 keys() 函数摘取名字部分。

模块搜索路径

当导入一个模块时,Python 解析器会去搜索该模块所在的位置,其搜索顺序为:

1、当前目录
2、如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录。
3、如果都找不到,Python会查看默认路径下的lib文件夹。UNIX下,默认路径一般为 /usr/local/lib/python/。

模块搜索路径存储在 system 模块的 sys.path 变量中。变量里包含当前目录,PYTHONPATH 和由安装过程决定的默认目录。

设置 PYTHONPATH 环境变量

作为环境变量,PYTHONPATH 由一个装在列表里的许多目录组成。PYTHONPATH 的语法和 shell 变量 PATH 的一样。
在 Windows 系统,典型的 PYTHONPATH 设置如下:

set PYTHONPATH=c:\python27\lib;

在 UNIX 系统,典型的 PYTHONPATH 设置如下:

set PYTHONPATH=/usr/local/lib/python

Python中的包

包:是一个分层次的文件目录结构,它定义了一个由模块及子包组成的 Python 应用环境。

简单来说,包就是文件夹,在文件夹中按一定的组织结构存放着模块和子包,该文件夹下必须有一个 init.py 文件(内容可为空),用于标识当前文件夹是一个包。

包的导入方式:

import 包名.模块名

函数调用方式:

包名.模块名.函数名

实例演示:

1、在工程文件夹下创建一个DEMO_package的包(文件夹),该包中含有 test_1.py 、 test_2.py 这两个模块,和一个 init.py 的包说明文件。
2、在工程文件夹下创建一个 test_package.py 的文件,用于测试包中内容的调用。

【test_1.py 文件内容】

# !/usr/bin/python
# -*- coding: UTF-8 -*-

def demo_1():
    print('这是包中的第一个模块文件。')

【test_2.py 文件内容】

# !/usr/bin/python
# -*- coding: UTF-8 -*-

def demo_2():
    print('这是包中的第二个模块文件。')

【init.py 文件内容】

# !/usr/bin/python
# -*- coding: UTF-8 -*-

if __name__ == '__main__':
    print('作为主程序运行')
else:
    print('DEMO_package 初始化完成')

也可省略,不填写。

【test_package.py 文件内容】
注意:该文件应该创建在与所在的 DEMO_package 包同级。

from DEMO_package.test_1 import demo_1   # 导入包中指定模块的指定函数
from DEMO_package.test_2 import demo_2

demo_1()  # 调用函数
demo_2()

此时执行程序,如无差错程序将输出:

DEMO_package 初始化完成
这是包中的第一个模块文件。
这是包中的第二个模块文件。

分析:以上为了举例,所以只在每个模块里放置了一个函数,其实你可以放置许多函数。你也可以在这些文件里定义 Python 的类,然后为这些类建一个包。

完整学习教程请访问Python3 入门教程——目录索引

最后修改:2022 年 06 月 09 日
如果觉得我的文章对你有用,请随意赞赏