模块的概念进一步增强了 Python 的模块化。你可以一起定义多个相关的函数,并加载所需的函数。模块是一个包含函数定义、类、变量、常量或任何其他 Python 对象的文件。此文件的内容可以被任何其他程序所利用。Python 提供了 import 关键字用于此目的。
函数是一段组织良好、可重用的代码,用来执行单一相关动作。函数为你的应用程序提供了更好的模块化,并且具有高度的代码复用性。
Python 模块示例
import math
print ("100 的平方根:", math.sqrt(100))
它将产生以下输出:
100 的平方根: 10.0
Python 内置模块
Python 的标准库捆绑了大量的模块。这些被称为内置模块。大多数这些内置模块是用 C 语言编写的(因为 Python 的参考实现是用 C 编写的),并且预编译成了库的一部分。这些模块包含了像系统特定的 OS 管理、磁盘 IO、网络等功能强大的功能。
这里有一个选择性的内置模块列表:
| 序号 |
名称与简要描述 |
| 1 |
os |
| 2 |
string |
| 3 |
re |
| 4 |
math |
| 5 |
cmath |
| 6 |
datetime |
| 7 |
gc |
| 8 |
asyncio |
| 9 |
collections |
| 10 |
functools |
| 11 |
operator |
| 12 |
pickle |
| 13 |
socket |
| 14 |
sqlite3 |
| 15 |
statistics |
| 16 |
typing |
| 17 |
venv |
| 18 |
json |
| 19 |
wsgiref |
| 20 |
unittest |
| 21 |
random |
| 22 |
sys |
| 23 |
requests |
Python 用户定义模块
任何带有 .py 扩展名并包含 Python 代码的文本文件基本上都是一个模块。它可以包含一个或多个函数的定义、变量、常量以及类。通过 import 语句可以从一个模块导入解释器会话或其他 Python 脚本中的任何 Python 对象。模块也可以包含可运行的代码。
创建 Python 模块
创建模块不过是使用任何编辑器保存 Python 代码。让我们将以下代码保存为 mymodule.py:
def SayHello(name):
print ("嗨 {}!你好吗?".format(name))
return
你现在可以在当前 Python 终端导入 mymodule。
>>> import mymodule
>>> mymodule.SayHello("Harish")
嗨 Harish!你好吗?
你也可以在一个 Python 脚本中导入一个模块。保存以下代码为 example.py:
import mymodule
mymodule.SayHello("Harish")
从命令终端运行这个脚本
嗨 Harish!你好吗?
import 语句
在 Python 中,import 关键字被用来从一个模块加载 Python 对象。这个对象可能是函数、类、变量等。如果一个模块包含多个定义,所有这些定义都会加载到命名空间中。
让我们将以下包含三个函数的代码保存为 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 语句会在当前命名空间加载这个模块中的所有函数。导入模块中的每个函数都是该模块对象的一个属性。
>>> dir(mymodule)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'average', 'power', 'sum']
要调用任何函数,使用模块对象的引用。例如,mymodule.sum()。
import mymodule
print ("总和:", mymodule.sum(10, 20))
print ("平均:", mymodule.average(10, 20))
print ("幂:", mymodule.power(10, 2))
它将产生以下输出:
总和: 30
平均: 15.0
幂: 100
from ... import 语句
import 语句将在当前命名空间加载模块的所有资源。可以使用这种语法从模块导入特定的对象。例如:
在 mymodule 中三个函数中只导入两个的可执行脚本 example.py。
from mymodule import sum, average
print ("总和:", sum(10, 20))
print ("平均:", average(10, 20))
它将产生以下输出:
总和: 30
平均: 15.0
注意不需要在调用函数时加上其模块的名字作为前缀。
from ... import * 语句
也可以使用以下导入语句从模块导入当前命名空间中的所有名称:
from modname import *
这提供了一种简单的方法来将模块中的所有项导入当前命名空间;然而,应该谨慎使用这条语句。
import ... as 语句
你可以为导入的模块分配一个别名。
from modulename import alias
在调用时应该加上该别名。
看看以下例子:
import mymodule as x
print ("总和:", x.sum(10, 20))
print ("平均:", x.average(10, 20))
print ("幂:", x.power(10, 2))
定位模块
当你导入一个模块时,Python 解释器会按照以下顺序搜索模块:
当前目录。
如果找不到模块,Python 接着搜索环境变量 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
命名空间和作用域
变量是映射到对象的名字(标识符)。命名空间是一个字典,其中包含变量名字(键)及其对应的对象(值)。
Python 语句可以访问本地命名空间和全局命名空间中的变量。如果本地和全局变量具有相同的名字,那么本地变量会遮盖全局变量。
每个函数都有自己的本地命名空间。类方法遵循与普通函数相同的范围规则。
Python 会做出有根据的猜测,判断变量是本地的还是全局的。它假设任何在函数内部赋值的变量都是本地的。
为了在函数内部给全局变量赋值,你必须首先使用 global 语句。
global VarName 告诉 Python VarName 是一个全局变量。Python 停止在本地命名空间中查找该变量。
示例
例如,我们在全局命名空间定义了一个变量 Money。在函数 Money 中,我们给 Money 赋值,因此 Python 认为 Money 是一个本地变量。然而,在设置本地变量 Money 的值之前就访问了它,导致了一个 UnboundLocalError 错误。取消注释 global 语句可以解决这个问题。
Money = 2000
def AddMoney():
Money = Money + 1
print (Money)
AddMoney()
print (Money)
模块属性
在 Python 中,模块是一个模块类的对象,因此它具有属性。
以下是模块属性:
__file__ 返回模块的物理名称。
__package__ 返回模块所属的包。
__doc__ 如果有的话返回位于模块顶部的文档字符串。
__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__ 属性:", mymodule.__file__)
print ("__doc__ 属性:", mymodule.__doc__)
print ("__name__ 属性:", mymodule.__name__)
它将产生以下输出:
__file__ 属性: C:\math\examples\mymodule.py
__doc__ 属性: The docstring of mymodule
__name__ 属性: mymodule
Python 的 __name__ 属性
Python 模块的 __name__ 属性具有重要的意义。让我们更详细地探讨一下。
在交互式 shell 中,__name__ 属性返回 '__main__'。
>>> __name__
'__main__'
如果你在解释器会话中导入任何模块,它返回该模块的名称作为该模块的 __name__ 属性。
>>> import math
>>> math.__name__
'math'
从 Python 脚本内部,__name__ 属性返回 '__main__'。
print ("__name__ 属性在脚本内部:", __name__)
在命令终端中运行此脚本:
__name__ 属性在脚本内部: __main__
此属性允许 Python 脚本作为可执行文件或模块使用。与 C++、Java、C# 等不同,在 Python 中没有 main() 函数的概念。扩展名为 .py 的 Python 程序脚本可以包含函数定义以及可执行的语句。
保存 mymodule.py 并带有以下代码:
"The docstring of mymodule"
def sum(x, y):
return x + y
print ("总和:", sum(10, 20))
你会看到 sum() 函数在其定义的同一个脚本中被调用。
总和: 30
现在让我们在另一个脚本 example.py 中导入此函数。
import mymodule
print ("总和:", mymodule.sum(10, 20))
它会产生以下输出:
总和: 30
总和: 30
“总和:30”出现了两次。第一次是在导入 mymodule 模块时发生的。导入模块中的可执行语句也被执行。第二次输出来自调用脚本,即 example.py 程序。
我们希望发生的情况是,当模块被导入时,只有函数被导入,而其可执行语句不应运行。这可以通过检查 __name__ 的值来完成。如果它是 '__main__',意味着它正在运行而不是被导入。有条件地包含函数调用等可执行语句。
在 mymodule.py 中添加 if 语句如下:
"The docstring of mymodule"
def sum(x, y):
return x + y
if __name__ == "__main__":
print ("总和:", sum(10, 20))
现在如果你运行 example.py 程序,你会发现 “总和:30” 输出仅出现一次。
总和: 30
dir() 函数
内置函数 dir() 返回一个排序后的字符串列表,包含由模块定义的名称。
列表包含模块中定义的所有模块、变量和函数的名称。以下是一个简单的示例:
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.py):
def SayHello(name):
print ("嗨 {}! 你好吗?".format(name))
return
我们可以从 Python 提示符导入模块并调用其函数:
>>> import test
>>> test.SayHello("Deepak")
嗨 Deepak! 你好吗?
但是,假设您需要修改 SayHello() 函数,如下所示:
def SayHello(name, course):
print ("嗨 {}! 你好吗?".format(name))
print ("欢迎来到 {} 教程由 TutorialsPoint 提供".format(course))
return
即使您编辑了 test.py 文件并保存了它,内存中加载的函数也不会更新。您需要用 imp 模块中的 reload() 函数来重新加载它。
>>> import imp
>>> imp.reload(test)
>>> test.SayHello("Deepak", "Python")
嗨 Deepak! 你好吗?
欢迎来到 Python 教程由 TutorialsPoint 提供
Python 中的包
包是一种层次化的文件目录结构,定义了一个包含模块、子包、子子包等等的单一 Python 应用环境。
考虑在 Phone 目录中可用的 Pots.py 文件。此文件包含以下源代码行:
def Pots():
print ("我是 Pots 电话")
类似地,我们还有另外两个具有相同名称的不同函数的文件:
Phone/Isdn.py 文件具有 Isdn() 函数
Phone/G3.py 文件具有 G3() 函数
现在,在 Phone 目录中创建另一个文件 __init__.py -
Phone/__init__.py
为了让所有函数在导入 Phone 时可用,你需要在 __init__.py 中放入显式的导入语句,如下所示:
from Pots import Pots
from Isdn import Isdn
from G3 import G3
在你将这些行添加到 __init__.py 后,当导入 Phone 包时,所有这些类都可用。
import Phone
Phone.Pots()
Phone.Isdn()
Phone.G3()
当执行上述代码时,会产生以下结果:
我是 Pots 电话
我是 3G 电话
我是 ISDN 电话
在上面的例子中,我们采用了每个文件中的单个函数的例子,但你可以在文件中包含多个函数。你也可以在那些文件中定义不同的 Python 类,然后你可以从这些类创建你的包。