Python 3 – 模块
模块可帮助你逻辑地组织你的Python代码。将相关代码组合到一个模块中,使代码更易于理解和使用。模块是Python对象,具有任意命名的属性,你可以绑定并引用它们。
简而言之,模块是一个包含Python代码的文件。一个模块可以定义函数、类和变量。一个模块也可以包含可执行代码。
实例
模块的Python代码通常存在一个名为module_name.py的文件中。下面是一个简单模块support.py的示例−
def print_func( par ):
print "Hello : ", par
return
导入语句
你可以通过在其他Python源文件中执行一个import语句,将任何Python源文件用作模块。import语句的语法如下−
import module1[, module2[,... moduleN]]
当解释器遇到一个import语句时,如果该模块存在于搜索路径中,则导入该模块。搜索路径是解释器在导入模块之前搜索的目录列表。例如,要导入模块hello.py,你需要在脚本顶部放置以下命令−
#!/usr/bin/python3
# 导入模块support
import support
# 现在,你可以按以下方式调用模块定义的函数
support.print_func("Zara")
当执行上述代码时,将产生以下结果−
Hello : Zara
一个模块只被加载一次,无论它被导入多少次。如果多次导入,则会防止多次执行模块。
from…import语句
Python的from语句允许你将一个模块的特定属性导入到当前命名空间中。from…import语法如下 −
from modname import name1[, name2[, ... nameN]]
例如,要从模块fib中导入函数fibonacci,请使用以下语句−
#!/usr/bin/python3
# Fibonacci numbers module
def fib(n): # 返回n以内的斐波那契数列
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a + b
return result
>>> from fib import fib
>>> fib(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
此语句不会将整个模块fib导入到当前命名空间中;它只会将模块fib中的fibonacci项引入到导入模块的全局符号表中。
from…import *语句
也可以使用以下导入语句将模块中的所有名称导入到当前命名空间中−
from modname import *
这提供了一种将模块中所有项目导入到当前命名空间中的简单方法;但是,应该谨慎使用此语句。
作为脚本执行模块
在模块中,模块的名称(作为字符串)可用作全局变量name的值。在模块中的代码将被执行,就像你导入它一样,但name设置为”main“。
在模块的末尾添加以下代码−
#!/usr/bin/python3
# Fibonacci numbers module
def fib(n): # 返回n以内的斐波那契数列
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a + b
return result
if __name__ == "__main__":
f = fib(100)
print(f)
运行上述代码时,将显示以下输出。
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
定位模块
当您导入模块时,Python解释器按以下顺序搜索模块 –
- 当前目录。
-
如果未找到模块,则Python会在shell变量PYTHONPATH中搜索每个目录。
-
如果所有其他失败,则Python会检查默认路径。在UNIX上,默认路径通常为 /usr/local/lib/python3/。
模块搜索路径存储在系统模块sys中,作为 sys.path 变量。sys.path变量包含当前目录、PYTHONPATH和与安装相关的默认值。
PYTHONPATH 变量
PYTHONPATH是一个环境变量,由一系列目录组成,其语法与shell变量PATH相同。
下面是Windows系统中的一个典型PYTHONPATH:
set PYTHONPATH = c:\python34\lib;
下面是UNIX系统中的一个典型PYTHONPATH:
set PYTHONPATH = /usr/local/lib/python
命名空间和作用域
变量是映射到对象的名称(标识符)。命名空间是变量名称(键)及其对应对象(值)的字典。
- Python语句可以访问局部命名空间和全局命名空间中的变量。如果本地变量和全局变量具有相同的名称,则本地变量将遮盖全局变量。
-
每个可调用对象(函数、方法等)都有自己的局部命名空间。
-
Python会根据上下文推断变量是局部变量还是全局变量。它假定在函数中赋值的任何变量都是局部变量。
-
因此,在函数内部为全局变量分配值,必须首先使用global语句。
-
语句 global VarName 告诉Python,VarName是一个全局变量。Python不会继续在本地命名空间查找该变量。
例如,我们在全局命名空间中定义了一个变量Money。在函数Money内部,我们为Money赋值,因此Python将Money视为局部变量。
但是,在设置Money值之前,我们访问了局部变量Money的值,因此,结果是UnboundLocalError。取消global语句可解决该问题。
#!/usr/bin/python3
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
# global Money
Money = Money + 1
print (Money)
AddMoney()
print (Money)
dir() 函数
dir()内置函数返回包含模块定义的名称的排序字符串列表。
列表包含在模块中定义的所有模块、变量和函数的名称。以下是一个简单的示例 –
#!/usr/bin/python3
# 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']
在此,特殊字符串变量 name 是模块的名称,file 是加载模块的文件名。
globals() 和 locals() 函数
globals() 和 locals() 函数可以根据它们被调用的位置返回全局和局部命名空间中的名称。
- 如果在函数内部调用 locals() ,它将返回可以从该函数访问的所有本地名称。
-
如果在函数内部调用 globals() ,它将返回可以从该函数全局访问的所有名称。
这两个函数的返回类型都是字典,因此可以使用 keys() 函数提取名称。
reload() 函数
当模块被导入到脚本中时,模块顶部部分的代码仅执行一次。
因此,如果要重新执行模块中的顶部代码,可以使用 reload() 函数。reload() 函数再次导入以前导入的模块。reload() 函数的语法如下:
reload(module_name)
其中,module_name 是您要重新载入的模块名称,而不是包含模块名称的字符串。例如,要重新加载hello模块,请执行以下操作:
reload(hello)
Python 中的包
包是层次结构的文件目录结构,用于定义由模块,子包,子子包等组成的单个Python应用程序环境。
考虑一个名为 Pots.py 的文件,它位于 Phone 目录中。该文件有以下源代码行:
#!/usr/bin/python3
def Pots():
print("I'm Pots Phone")
类似地,我们有其他两个文件,具有相同名称的不同函数。它们是:
- 文件 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 包时将获得所有这些类。
#!/usr/bin/python3
# 现在导入你的 Phone 包
import Phone
Phone.Pots()
Phone.Isdn()
Phone.G3()
当上面的代码被执行时,它会产生以下结果-
I'm Pots Phone
I'm 3G Phone
I'm ISDN Phone
在上面的示例中,我们以每个文件一个函数的方式进行了示例,但您可以在文件中保留多个函数。您也可以在这些文件中定义不同的Python类,然后可以根据这些类创建您的包。