Python 简明教程

Python - Modules

Python Modules

Python 中 module 的概念进一步提高了模块化。你可以一起定义多个相关的函数并加载所需的函数。模块是一个包含函数定义的文件, classesvariables 、常量或任何其他 Python 对象。此文件的内容可以供任何其他程序使用。Python 有 import 关键字用于此目的。

Example of Python Module

import math
print ("Square root of 100:", math.sqrt(100))

它将生成以下 output

Square root of 100: 10.0

Python Built-in Modules

Python 的标准库附带了大量模块。它们被称为内置模块。大多数这些内置模块是用 C 编写的(因为 Python 的参考实现是 C),并且预编译到库中。这些模块封装了有用的功能,如特定于系统操作系统的管理、磁盘 IO、网络等。

以下是内置模块的选择列表 -

Python User-defined Modules

带有 .py 扩展名的任何文本文件和包含 Python 代码的文本文件基本上都是一个模块。它可以包含一个或多个函数、变量、常量的定义以及类。来自模块的任何 Python 对象都可以通过 import 语句在解释器会话或另一个 Python 脚本中使用。模块还可以包含可运行的代码。

Creating a Python Module

创建模块只不过是用任何编辑器的帮助保存 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?

The import Statement

在 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 ("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

The from …​ import Statement

import 语句将会加载模块的所有资源到当前名称空间中。可以通过使用此语法从模块中导入特定对象。例如 −

mymodule 中的三个函数中,只有两个被导入到以下可执行脚本 example.py

from mymodule import sum, average
print ("sum:",sum(10,20))
print ("average:",average(10,20))

它将生成如下输出:

sum: 30
average: 15.0

注意,不需要通过给函数加上其模块名前缀来调用它。

The from…​import * Statement

还可以通过使用以下 import 语句将模块中的所有名称导入到当前名称空间中 −

from modname import *

这提供了一种将模块中的所有项导入当前名称空间的简单方法;但是,此语句应该谨慎使用。

The import …​ as Statement

您可以为导入的模块指定一个别名。

from modulename as alias

调用时 alias 应该加在函数前面。

看看以下 example

import mymodule as x
print ("sum:",x.sum(10,20))
print ("average:", x.average(10,20))
print ("power:", x.power(10, 2))

Locating Modules

当你导入模块时,Python 解释器按以下顺序搜索模块 −

  1. The current directory.

  2. 如果找不到模块,Python 接着搜索 shell 变量 PYTHONPATH 中的每个目录。

  3. 如果仍失败,Python 会检查默认路径。在 UNIX 中,此默认路径通常为 /usr/local/lib/python/。

模块搜索路径存储在系统模块 sys 中,作为 sys.path 变量。sys.path 变量包含当前目录、PYTHONPATH 和与安装相关的默认值。

The PYTHONPATH Variable

PYTHONPATH 是一个环境变量,包括目录列表。PYTHONPATH 的语法与 shell 变量 PATH 相同。

这是 Windows 系统中的典型 PYTHONPATH −

set PYTHONPATH = c:\python20\lib;

这是 UNIX 系统中的典型 PYTHONPATH −

set PYTHONPATH = /usr/local/lib/python

Namespaces and Scoping

变量是映射到对象的名称(标识符)。命名空间是由变量名称(键)及其对应对象(值)组成的字典。

  1. Python 语句可以在局部命名空间和全局命名空间中访问变量。如果一个局部变量和一个全局变量具有相同的名称,则局部变量会隐藏全局变量。

  2. 每个函数都有自己的局部命名空间。类方法遵循与普通函数相同的范围规则。

  3. Python 对变量是局部变量还是全局变量做出明智的猜测。它假定在函数中赋值的任何变量都是局部变量。

  4. 为了在函数中为全局变量赋值,你必须首先使用 global 语句。

  5. 语句 global VarName 告诉 Python VarName 是一个全局变量。Python 会停止在局部命名空间中搜索该变量。

Example

例如,我们在全局命名空间中定义了一个变量 Money。在函数 Money 中,我们为 Money 赋值,因此 Python 假定 Money 是局部变量。但是,我们在设置局部变量 Money 的值之前访问了它的值,因此导致 UnboundLocalError。取消对 global 语句的注释可以解决该问题。

Money = 2000
def AddMoney():
   # Uncomment the following line to fix the code:
   # global Money
   Money = Money + 1

print (Money)
AddMoney()
print (Money)

Module Attributes

在 Python 中,模块是模块类的一个对象,因此它以属性为特征。

以下为模块属性 −

  1. file 返回模块的物理名称。

  2. package 返回模块所属的包。

  3. doc 返回模块顶部的文档字符串(如果有)。

  4. dict 返回模块的整个作用域

  5. name 返回模块的名称

Example

假设以下代码已保存为 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

The _name_Attribute

Python 模块的 name 属性非常重要。让我们详细了解一下。

在交互式 shell 中, name 属性会返回“ main

>>> __name__
'__main__'

如果你在解释器会话中导入任何模块,它会返回模块的名称作为该模块的 name 属性。

>>> import math
>>> math.__name__
'math'

从 Python 脚本内部, name 属性会返回“ main

#example.py
print ("__name__ attribute within a script:", __name__)

在命令终端中运行此代码−

__name__ attribute within a script: __main__

此属性允许将 Python 脚本用作可执行文件或模块。与 C++、Java、C# 等不同,在 Python 中,不存在 main() 函数的概念。带 .py 扩展名的 Python 程序脚本可以包含函数定义以及可执行语句。

保存 mymodule.py 及其以下代码−

"The docstring of mymodule"
def sum(x,y):
   return x+y

print ("sum:",sum(10,20))

你可以看到 sum() 函数在其被定义的同一脚本中被调用。

sum: 30

现在让我们在另一个脚本 example.py 中导入此函数。

import mymodule
print ("sum:",mymodule.sum(10,20))

它将生成以下 output

sum: 30
sum: 30

输出 “sum: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:",sum(10,20))

现在,如果你运行 example.py 程序,你会发现 sum:30 输出只出现了一次。

sum: 30

The dir( ) Function

内置函数 dir() 返回一个排序的字符串列表,其中包含模块定义的名称。

该列表包含模块中定义的所有模块、变量和函数的名称。以下是一个简单的示例 −

# Import built-in module 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']

The reload() Function

有时,你可能需要重新加载模块,尤其是在使用 Python 的交互式解释器会话时。

假设我们有一个测试模块 (test.py),其中有以下函数−

def SayHello(name):
   print ("Hi {}! How are you?".format(name))
   return

我们可以导入该模块并从 Python 提示符调用其函数,如下所示−

>>> import test
>>> test.SayHello("Deepak")
Hi Deepak! How are you?

但是,假设你需要修改 SayHello() 函数,比如−

def SayHello(name, course):
   print ("Hi {}! How are you?".format(name))
   print ("Welcome to {} Tutorial by TutorialsPoint".format(course))
   return

即使编辑 test.py 文件并保存它,内存中加载的函数也不会更新。你需要重新加载它,使用 imp 模块中的 reload() 函数。

>>> import imp
>>> imp.reload(test)
>>> test.SayHello("Deepak", "Python")
Hi Deepak! How are you?
Welcome to Python Tutorial by TutorialsPoint

Packages in Python

包是一个分层的目录结构,它定义了一个由模块、子包、子子包等等组成的单个 Python 应用程序环境。

考虑 Phone 目录中提供的一个文件 Pots.py。该文件中有一行源代码 −

def Pots():
   print "I'm Pots Phone"

同样的方式,我们还有另外两个具有与上面相同名称的不同功能的文件 −

  1. Phone/Isdn.py 文件具有 Isdn() 函数

  2. Phone/G3.py 文件具有 G3() 函数

现在,在 Phone 目录中创建另一个文件 init .py −

  1. Phone/init.py

为了使导入 Phone 时所有函数可用,需要在 init .py 中放入显式 import 语句,如下所示 −

from Pots import Pots
from Isdn import Isdn
from G3 import G3

在将这些行添加到 init .py 后,在导入 Phone 包时,所有这些类都可用。

# Now import your Phone Package.
import Phone

Phone.Pots()
Phone.Isdn()
Phone.G3()

执行上述代码后,将生成以下结果 −

I'm Pots Phone
I'm 3G Phone
I'm ISDN Phone

在上面的示例中,我们采用了每个文件中单个函数的示例,但您可以在文件中保留多个函数。您还可以在这些文件中定义不同的 Python 类,然后可以从这些类中创建包。