模块的概念进一步增强了 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 类,然后你可以从这些类创建你的包。