Python - 模块
Python 模块
Python 中的 module 概念进一步提升了模块化。您可以将多个相关的 function 一起定义并加载所需的 function。module 是一个包含 function、class、变量、常量或其他任何 Python 对象的文件。该文件的内容可以被任何其他程序使用。Python 为此提供了 import 关键字。
function 是一块有组织的、可重用的代码块,用于执行单一相关的操作。function 为您的应用程序提供了更好的模块化,并具有高度的代码重用性。
Python 模块示例
import math
print ("Square root of 100:", math.sqrt(100))
它将产生以下 output −
Square root of 100: 10.0
Python 内置模块
Python 的标准库捆绑了大量模块。这些被称为内置模块。其中大多数内置模块是用 C 语言编写的(因为 Python 的参考实现是用 C 编写的),并预编译到库中。这些模块封装了有用的功能,如特定于系统的 OS 管理、磁盘 IO、网络等。
以下是内置模块的精选列表 −
| 序号 | 名称 & 简要描述 |
|---|---|
1 |
os 该模块为多个操作系统 function 提供统一的接口。 |
2 |
string 该模块包含多个用于 string 处理的 function |
3 |
re 该模块提供了一组强大的 regular expression 功能。Regular expression (RegEx) 允许在 string 中对模式进行强大的搜索和匹配 |
4 |
math 该模块实现了针对 floating point numbers 的多种数学运算。这些 function 通常是平台 C 库 function 的薄包装器。 |
5 |
cmath 该模块包含针对 complex numbers 的多种数学运算。 |
6 |
datetime 该模块提供处理日期和一天内时间的功能。它包装了 C 运行时库。 |
7 |
gc 该模块为内置垃圾回收器提供接口。 |
8 |
asyncio 该模块定义了异步处理所需的功能 |
9 |
Collections 该模块提供高级 Container 数据类型。 |
10 |
functools 该模块具有高阶 function 和对 callable objects 的操作。在函数式编程中很有用 |
11 |
operator 对应标准 operator 的 function。 |
12 |
pickle 将 Python 对象转换为字节流并反向转换。 |
13 |
socket 低级网络接口。 |
14 |
sqlite3 使用 SQLite 3.x 实现的 DB-API 2.0。 |
15 |
statistics 数学统计 function |
16 |
typing 对 type hints 的支持 |
17 |
venv 创建虚拟环境。 |
18 |
json 编码和解码 JSON 格式。 |
19 |
wsgiref WSGI 实用工具和参考实现。 |
20 |
unittest Python 的单元测试框架。 |
21 |
random 生成伪随机数 |
22 |
sys 提供与解释器紧密交互的 function。 |
23 |
requests 它通过提供用户友好的接口来发送和处理响应,从而简化 HTTP 请求。 |
24 |
itertools iterator object 用于遍历 collection(例如 list、tuple 等)。该模块提供各种用于创建和操作 iterator 的工具。 |
25 |
locale Python 中的 locale 模块用于设置和管理数据格式化的文化约定。它允许程序员通过更改数字、日期和货币的显示方式,使其程序适应不同的语言和区域格式标准。 |
Python 用户定义模块
任何带有 .py 扩展名的文本文件并包含 Python 代码的基本上就是一个 module。它可以包含一个或多个 function、变量、常量以及 class 的定义。通过 import 语句,来自 module 的任何 Python 对象都可以被提供给解释器会话或其他 Python 脚本。module 也可以包含可运行的代码。
创建 Python 模块
创建模块无非就是使用任何编辑器保存 Python 代码。我们将以下代码保存为 mymodule.py
def SayHello(name):
print ("Hi {}! How are you?".format(name))
return
现在你可以在当前的 Python 终端中导入 mymodule。
>>> import mymodule
>>> mymodule.SayHello("Harish")
Hi Harish! How are you?
你也可以在一个 Python 脚本中导入另一个模块。将以下代码保存为 example.py
import mymodule
mymodule.SayHello("Harish")
从命令终端运行此脚本
Hi Harish! How are you?
import 语句
在 Python 中,提供了 import 关键字来从一个模块加载 Python 对象。该对象可以是 function、class、variable 等。如果一个模块包含多个定义,它们都会被加载到 namespace 中。
我们将包含三个 function 的以下代码保存为 mymodule.py。
def sum(x,y): return x+y def average(x,y): return (x+y)/2 def power(x,y): return x**y
import mymodule 语句会将该模块中的所有 function 加载到当前 namespace 中。导入模块中的每个 function 都是该模块对象的 attribute。
>>> dir(mymodule) ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'average', 'power', 'sum']
要调用任何 function,请使用模块对象的引用。例如,mymodule.sum()。
import mymodule
print ("sum:",mymodule.sum(10,20))
print ("average:",mymodule.average(10,20))
print ("power:",mymodule.power(10, 2))
它将产生以下 output −
sum:30 average:15.0 power:100
from ... import 语句
import 语句会将模块的所有资源加载到当前 namespace 中。可以使用这种语法从模块中导入特定的对象。例如 −
在 mymodule 中的三个 function 中,以下可执行脚本 example.py 只导入了两个
from mymodule import sum, average
print ("sum:",sum(10,20))
print ("average:",average(10,20))
它将产生以下 output −
sum: 30 average: 15.0
注意,function 调用时不需要在其前面加上模块名称。
from...import * 语句
也可以使用以下 import 语句将一个模块中的所有名称导入到当前 namespace 中 −
from modname import *
这提供了一种简单的方法将模块中的所有项导入到当前 namespace 中;但是,此语句应谨慎使用。
import ... as 语句
你可以为导入的模块指定一个别名。
from modulename as alias
调用 function 时需要在前面加上 alias。
查看以下 example −
import mymodule as x
print ("sum:",x.sum(10,20))
print ("average:", x.average(10,20))
print ("power:", x.power(10, 2))
定位模块
当你导入一个模块时,Python 解释器会按照以下顺序搜索模块 −
当前目录。
如果没有找到模块,Python 然后搜索 shell 变量 PYTHONPATH 中的每个目录。
如果以上均失败,Python 会检查默认路径。在 UNIX 上,默认路径通常是 /usr/local/lib/python/。
模块搜索路径存储在系统模块 sys 中,作为 sys.path 变量。sys.path 变量包含当前目录、PYTHONPATH 和依赖安装的默认路径。
PYTHONPATH 变量
PYTHONPATH 是一个环境变量,由一个目录列表组成。PYTHONPATH 的语法与 shell 变量 PATH 相同。
这是来自 Windows 系统的典型 PYTHONPATH −
set PYTHONPATH = c:\python20\lib;
这是来自 UNIX 系统的典型 PYTHONPATH −
set PYTHONPATH = /usr/local/lib/python
命名空间和作用域
变量是映射到对象的名称(标识符)。namespace 是变量名称(键)和其对应对象(值)的字典。
Python 语句可以访问 local namespace 和 global namespace 中的变量。如果局部变量和全局变量同名,则局部变量会遮蔽全局变量。
每个 function 都有自己的 local namespace。class 方法遵循与普通 function 相同的作用域规则。
Python 会根据经验猜测变量是 local 还是 global。它假设在 function 中被赋值的任何变量都是 local 的。
为了在 function 内给 global 变量赋值,必须先使用 global 语句。
global VarName 语句告诉 Python,VarName 是 global 变量。Python 停止在 local namespace 中搜索该变量。
示例
例如,我们在 global namespace 中定义了一个变量 Money。在 function Money 内,我们给 Money 赋值,因此 Python 假设 Money 是 local 变量。然而,我们在设置 local 变量 Money 的值之前就访问了它的值,因此结果是 UnboundLocalError。取消注释 global 语句即可修复这个问题。
Money = 2000 def AddMoney(): # 取消注释以下行以修复代码: # global Money Money = Money + 1 print (Money) AddMoney() print (Money)
模块属性
在 Python 中,module 是 module class 的对象,因此它具有属性。
以下是模块属性 −
__file__ 返回模块的物理名称。
__package__ 返回模块所属的 package。
__doc__ 返回模块顶部的 docstring(如果有的话)
__dict__ 返回模块的整个作用域
__name__ 返回模块的名称
示例
假设以下代码保存为 mymodule.py
"The docstring of mymodule" def sum(x,y): return x+y def average(x,y): return (x+y)/2 def power(x,y): return x**y
让我们通过在以下脚本中导入它来检查 mymodule 的属性 −
import mymodule
print ("__file__ attribute:", mymodule.__file__)
print ("__doc__ attribute:", mymodule.__doc__)
print ("__name__ attribute:", mymodule.__name__)
它将产生以下 output −
__file__ attribute: C:\math\examples\mymodule.py __doc__ attribute: The docstring of mymodule __name__ attribute: mymodule
__name__ 属性
Python 模块的 __name__ 属性具有重要意义。让我们更详细地探讨它。
在交互式 shell 中,__name__ 属性返回 '__main__'
>>> __name__ '__main__'
如果你在解释器会话中导入任何模块,它会返回该模块名称作为该模块的 __name__ 属性。
>>> import math >>> math.__name__ 'math'
从 Python 脚本内部,__name__ 属性返回 '__main__'
#example.py
print ("脚本内的 __name__ 属性:", __name__)
在命令终端中运行此代码 −
脚本内的 __name__ 属性: __main__
这个属性允许 Python 脚本用作可执行文件或模块。与 C++、Java、C# 等不同,Python 中没有 main() function 的概念。带有 .py 扩展名的 Python 程序脚本可以包含 function 定义以及可执行语句。
保存 mymodule.py,并使用以下代码 −
"mymodule 的文档字符串"
def sum(x,y):
return x+y
print ("sum:",sum(10,20))
你可以看到 sum() function 在其定义的同一脚本中被调用。
sum: 30
现在让我们在另一个脚本 example.py 中导入这个 function。
import mymodule
print ("sum:",mymodule.sum(10,20))
它将产生以下 output −
sum: 30 sum: 30
输出 "sum:30" 出现了两次。第一次是在导入 mymodule 模块时。导入模块中的可执行语句也会运行。第二次输出来自调用脚本,即 example.py 程序。
我们希望发生的情况是,当模块被导入时,只导入 function,其可执行语句不应运行。这可以通过检查 __name__ 的值来实现。如果它是 __main__,则表示它正在运行而不是被导入。有条件地包含像 function 调用这样的可执行语句。
在 mymodule.py 中添加 if 语句,如下所示 −
"mymodule 的文档字符串"
def sum(x,y):
return x+y
if __name__ == "__main__":
print ("sum:",sum(10,20))
现在如果你运行 example.py 程序,你会发现 sum:30 输出只出现一次。
sum: 30
dir( ) 函数
内置函数 dir() 返回一个字符串的排序列表,这些字符串包含模块定义的名称。
该列表包含模块中定义的所有 modules、variables 和 functions 的名称。以下是一个简单的例子 −
# 导入内置模块 math import math content = dir(math) print (content)
执行上述代码时,会产生以下结果 −
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
reload() 函数
有时你可能需要重新加载一个模块,尤其是在使用 Python 的交互式解释器会话时。
假设我们有一个 test 模块(test.py),其中包含以下 function −
def SayHello(name):
print ("Hi {}! How are you?".format(name))
return
我们可以在 Python 提示符下导入模块并调用其 function,如下所示 −
>>> import test
>>> test.SayHello("Deepak")
Hi Deepak! How are you?
然而,假设你需要修改 SayHello() function,例如 −
def SayHello(name, course):
print ("Hi {}! How are you?".format(name))
print ("Welcome to {} Tutorial by ".format(course))
return
即使你编辑 test.py 文件并保存它,加载到内存中的 function 也不会更新。你需要使用 imp 模块中的 reload() function 来重新加载它。
>>> import imp
>>> imp.reload(test)
>>> test.SayHello("Deepak", "Python")
Hi Deepak! How are you?
Welcome to Python Tutorial by
Python 中的 Packages
一个 package 是一个分层的文件目录结构,它定义了一个单一的 Python 应用程序环境,该环境由 modules、subpackages 和 sub-subpackages 等组成。
考虑一个位于 Phone 目录中的文件 Pots.py。该文件包含以下源代码行 −
def Pots(): print "I'm Pots Phone"
类似地,我们还有另外两个文件,它们包含与上面同名的不同 functions −
Phone/Isdn.py 文件包含 function Isdn()
Phone/G3.py 文件包含 function G3()
现在,在 Phone 目录中再创建一个 __init__.py 文件 −
- Phone/__init__.py
为了在导入 Phone 时使所有 functions 可用,你需要在 __init__.py 中添加明确的 import 语句,如下所示 −
from Pots import Pots from Isdn import Isdn from G3 import G3
在将这些行添加到 __init__.py 后,当你导入 Phone package 时,所有这些 classes 都将可用。
# 现在导入你的 Phone Package。 import Phone Phone.Pots() Phone.Isdn() Phone.G3()
执行上述代码时,会产生以下结果 −
I'm Pots Phone I'm 3G Phone I'm ISDN Phone
在上面的示例中,我们在每个文件中只取了一个 function 的例子,但你可以在文件中放置多个 functions。你也可以在那些文件中定义不同的 Python classes,然后基于那些 classes 创建你的 packages。