十三、模块
一、模块概述
Python 中一个以 .py 结尾的源文件即为一个模块(Module)。其中可以包含变量、函数和类等。通常情况下,我们把能够实现某一特定功能的代码放置在一个文件中作为一个模块。
使用模块提高了代码的可维护性,也提高了代码的复用性。即编写好一个模块后,只要是实现该功能的程序,都可以导入这个模块实现。另外,使用模块也可以避免名称冲突,相同名字的函数或变量可以分别存在于不同的模块中。
二、创建模块
模块名区分大小写,且不能与 Python 自带的模块重名。
创建一个模块 my_add.py:
num = 100
def add(a, b):
"""求两个数的和"""
return a + b
三、导入模块
3.1、全部导入 import
导入模块的所有成员,通过 模块名.成员名 的方式访问。即使多次使用 import 导入同一模块,模块也只会被导入一次
3.1.1、语法
import 模块名 [as 别名]
3.1.2、案例
在同一目录下创建一个 main.py 文件,在其中导入 my_add.py 模块并使用。
# 导入模块
import my_add
# 使用模块
print(my_add.add(1, 2))
print(my_add.num)
也可以在导入模块时给模块起别名:
# 导入模块并起别名
import my_add as al
# 使用模块
print(al.add(1, 2))
print(al.num)
3.2、局部导入 from import
指定导入模块的部分成员,直接通过成员名的方式访问。只能使用其导入的成员,未导入的成员不能使用。如果多个模块中存在重名成员,后一次导入会覆盖前一次导入。
3.2.1、语法
from 模块名 import 成员名1 [as 别名], 成员名2 [as 别名], ...
3.2.2、案例
创建新的模块 my_multipy.py
num = 200
_str1 = "abc"
def multi(a, b):
"""求两个数的积"""
return a * b
只能使用导入的成员
from my_add import add
print(add(1, 2))
print(num) # NameError: name 'num' is not defined
重名变量,后一次导入会覆盖前一次导入
# 导入模块
from my_add import add, num
from my_multipy import num
# 使用模块
print(add(1, 2))
print(num)
通过别名区分不同模块的变量
# 导入模块
from my_add import add, num as al
from my_multipy import num as m1
# 使用模块
print(add(1, 2))
print(al)
print(m1)
3.3、局部导入 from import *
导入模块中所有不以单下划线开头的成员,直接通过成员名的方式访问。
3.3.1、语法
from 模块名 import *
3.3.2、案例
# 导入模块
from my_add import *
# 使用模块
print(add(1, 2))
print(num)
print(_str1) # 注意:_str1 以下划线开头,不会被导入,此处会报错 NameError
3.4、模块搜索顺序
当导入一个模块时,会按照以下顺序进行查找:
-
(1)、当前目录。
-
(2)、PYTHONPATH 环境变量中的目录。
-
(3)、包含标准 Python 模块以及这些模块所依赖的任何 extension module 的目录。
可以使用以下方式查看模块搜索顺序:
import sys
print(sys.path)
也可以通过 sys.path.append(路径) 向 sys.path 中临时添加路径:
import sys
print(sys.path)
sys.path.append("../../...")
print(sys.path)
3.5、all
使用 from 模块名 import * 导入模块时,可以在被导入的模块中使用 __all__ 设置哪些内容可以被导入。__all__ 的设置只针对使用 from 模块名 import * 导入模块时有效。
在 my_add.py 中向 __all__ 添加部分元素:
__all__ = ["num", "add"] # 内容必须要用引号引起来
num = 100
num1 = 200
_str1 = "abc"
def add(a, b):
"""求两个数的和"""
return a + b
在 main.py 中使用 from my_add import * 导入模块中的内容。没在 all 中的变量在使用时会报错:
from my_add import *
print(add(1, 2))
print(num)
print(num1) # NameError: name 'num1' is not defined
而使用 import my_add 全局导入模块后可以正常使用所有元素:
import my_add
print(my_add.add(1, 2))
print(my_add.num)
print(my_add.num1) # 正常输出: 200
3.6、name
在 Python 中,__name__ 是一个特殊的内置变量:
-
当一个 Python 文件被直接运行时,该文件的
__name__属性值为"__main__"。 -
当一个 Python 文件作为模块被导入时,
__name__属性会被设置为该模块的名称(即文件名,不包含.py后缀)。
3.6.1、导入模块时测试代码被执行
有时我们会在模块中写一些测试代码,当模块被其他文件导入时这些测试代码会被执行。
在 my_add.py 中写一些测试代码:
__all__ = ["num", "add"]
num = 100
num1 = 200
str1 = "abc"
def add(a, b):
"""求两个数的和"""
return a + b
print(add(10, 20))
在 main.py 中导入模块,发现 my_add.py 中的测试代码被执行了:
import my_add
3.6.2、使用 __name__ == "__main__" 避免测试代码被执行
为了避免模块被导入时测试代码被执行,我们可以在被导入模块中添加对 __name__ 属性的检查:
"""my_add.py"""
__all__ = ["num", "add"]
num = 100
num1 = 200
_str1 = "abc"
def add(a, b):
"""求两个数的和"""
return a + b
print(__name__)
if __name__ == "__main__":
print(add(10, 20))
此时再在 main.py 中导入模块,测试代码不会被执行:
"""main.py"""
import my_add
3.7、dir()
dir() 是一个内置函数,主要用于列出对象的属性和方法,或者列出当前作用域中定义的名称,并以一个字符串列表的形式返回。
- 当你将一个模块作为
dir()的参数时,它会返回该模块中定义的名称列表,包括函数、类、变量等。
import math
# 查看 math 模块下的内容
print(dir(math))
当你将一个对象作为 dir() 的参数时,它会返回该对象的属性和方法列表。
class MyClass:
def __init__(self):
self.x = 1
self.y = 2
def method1(self):
pass
obj = MyClass()
print(dir(obj))
当你不传递任何参数调用 dir() 时,它会列出当前作用域中定义的名称,包括变量、函数、类等。
def my_function():
pass
variable = 10
print(dir()) # 列出当前作用域中的名称

浙公网安备 33010602011771号