模块机制

Python 模块机制

Python 模块只是一个 Python 源文件,它可以公开类,函数和全局变量。

>>> import urllib
>>> dir(urllib)
['ContentTooShortError', 'FancyURLopener', 'MAXFTPCACHE',...]
>>> help(urllib.urlopen)
Help on function urlopen in module urllib:
urlopen(url, data=None, proxies=None, context=None)
Create a file-like object for the specified URL to read from.

命名空间

从其他 Python 源文件导入时,文件名将被视为命名空间。命名空间是从命名到对象的映射。以下有一些命名空间的例子:内置命名(像 abs() 这样的函数,以及内置异常名)集,模块中的全局命名,函数调用中的局部命名。在 Python 中,作用域是由命名空间按特定的层级结构组合起来的。作用域一定是命名空间,但命名空间不一定是作用域。

某种意义上讲对象的属性集也是一个命名空间;关于命名空间需要了解的一件很重要的事就是不同命名空间中的命名没有任何联系,例如两个不同的模块可能都会定义一个名为 maximize 的函数而不会发生混淆--用户必须以模块名为前缀来引用它们。

# 文件目录
someDir/
main.py
siblingModule.py
# siblingModule.py
def siblingModuleFun():
print('Hello from siblingModuleFun')
def siblingModuleFunTwo():
print('Hello from siblingModuleFunTwo')
# main.py
# 引入模块
import siblingModule
import siblingModule as sibMod
sibMod.siblingModuleFun()
# 直接引入对应函数名
from siblingModule import siblingModuleFun
siblingModuleFun()
# 捕获模块异常
try:
# Import 'someModuleA' that is only available in Windows
import someModuleA
except ImportError:
try:
# Import 'someModuleB' that is only available in Linux
import someModuleB
except ImportError:

Python 中任何一个“.”之后的命名为属性--例如,表达式 z.real 中的 real 是对象 z 的一个属性。严格来讲,从模块中引用命名是引用属性:表达式 modname.funcname 中,modname 是一个模块对象,funcname 是它的一个属性。因此,模块的属性和模块中的全局命名有直接的映射关系:它们共享同一命名空间。

不同的命名空间在不同的时刻创建,有不同的生存期。包含内置命名的命名空间在 Python 解释器启动时创建,会一直保留,不被删除。模块的全局命名空间在模块定义被读入时创建,通常,模块命名空间也会一直保存到解释器退出。由解释器在最高层调用执行的语句,不管它是从脚本文件中读入还是来自交互式输入,都是 main 模块的一部分,所以它们也拥有自己的命名空间;内置命名也同样被包含在一个模块中,它被称作 builtin。

当函数被调用时创建一个局部命名空间,函数反正返回过抛出一个未在函数内处理的异常时删除;当然,每一个递归调用拥有自己的命名空间。

包是一种组织管理代码的方式,包里面存放的是模块;用于将模块包含在一起的文件夹就是包。

# 目录格式
someDir/
main.py
subModules/
__init__.py
subA.pys
subSubModules/
__init__.py
subSubA.py
# subA.py
def subAFun():
print('Hello from subAFun')
def subAFunTwo():
print('Hello from subAFunTwo')
# subSubA.py
def subSubAFun():
print('Hello from subSubAFun')
def subSubAFunTwo():
print('Hello from subSubAFunTwo')
# __init__.py from subDir
# 将 'subAFun()' 与 'subAFunTwo()' 添加到 'subModules' 命名空间
from subA import *
# 假设 'subSubModules' 中的 '__init__.py' 为空
# 将 'subSubAFun()' 与 'subSubAFunTwo()' 添加到 'subModules' 命名空间
from subSubModules.subSubA import *
# 假设 'subSubModules' 中的 '__init__.py' 不为空,包含了 'from .subSubA import *'
# __init__.py,将 'subSubAFun()' 与 'subSubAFunTwo()' 添加到 'subSubModules' 命名空间
from subSubA import *
# 将 'subSubAFun()' 与 'subSubAFunTwo()' 添加到 'subModules' 命名空间
from subSubDir import *
# main.py
import subDir
subDir.subAFun() # Hello from subAFun
subDir.subAFunTwo() # Hello from subAFunTwo
subDir.subSubAFun() # Hello from subSubAFun
subDir.subSubAFunTwo() # Hello from subSubAFunTwo

__init__.py 中也支持使用 __all__ 变量来声明所有需要导出的子模块:

import submodule1
import submodule2
__all__ = ['submodule1', 'submodule2']