Python核心编程笔记(第12章 模块)

采用书籍Python核心编程(第二版),人民邮电出版社,2008年7月第1版。本书以Python2.5为主,但笔记主要以Python3.6为主。

第12章

模块是用来组织Python代码的方法,而包是用来组织模块的

12.1 模块和文件

  1. 代码量变大—>把代码分成有组织的代码段,彼此能够交互—>代码可以共享,实现重用。那些自我包含并且有组织的代码片段就是模块(module),吧其他模块加入到你的模块中的操作叫做导入(import)
  2. 如果说模块(module)是按照逻辑来组织Python代码的方法,那么文件便是物理层上组织模块的方法。一个文件被看作一个独立模块,一个模块也可以被看作是一个文件
  3. 模块命名空间(也叫名称空间,namespace):从名称到对象的关系映射集合,模块的属性名称均属于该集合。每个模块都定义了自己的唯一的名称空间。
  4. 搜索路径和路径搜索:前者为名词,后者为动词。前者是一组预定义有用途的目录,后者是查找某个文件的操作。默认搜索路径是在安装时指定的,可以用环境变量PYTHOINPATH或保存在sys模块中的sys.path变量进行修改。

12.2 名称空间

  1. 名称空间是名称(标识符)到对象的映射。向名称中添加名称的操作过程涉及绑定标识符到指定对象的操作(以及给对象的引用计数加1)。
  2. 在程序执行期间,有2个或3个活动的名称空间:局部名称空间、全局名称空间和内建名称空间。局部名称空间会变化,可能有可能无,所以是“2个或3个”。
  3. Python解释器会首先加载内建名称空间。随后加载全局名称空间,它会在模块开始执行后变为活动名称空间。如果在执行期间调用了一个函数,那么将会创建除第三个名称空间,即局部名称空间。(Java中一对新的大括号会生成一个局部作用域,Python和其不同)
  4. 名称空间和变量作用域:名称空间是纯粹意义上的名字和对象件的映射关系,而作用域还指出了在代码中可以访问这些名字的物理位置。
  5. 名字查找:访问一个属性时,按局部名称空间—>全局名称空间—>内建名称空间的顺序查找它的名字。若没有找到,就会出现NameError;若局部和全局或内建有相同的名称,访问时会覆盖。
  6. Python中一切皆对象。你可以在任何需要放置数据的地方获得一个名称空间。

12.3 导入模块

  1. 导入语句:import module。
  2. 模块在顶层导入,它的作用域就是全局的;在函数中导入,它的作用域是局部的。
  3. 如果模块被第一次导入,它将被加载并执行。模块的顶层代码将直接被执行,包括全局变量和函数的声明(函数本身并不会被执行,因为没有调用啊哈哈哈)。
  4. 一个模块可被导入多次。,但只被加载和执行一次(就是第一次),这样阻止了多重导入时代码被多次执行。若用户自定义模块被修改需重新导入,需使用reload。
  5. from-import语句:把模块中的属性导入到当前的名称空间,方便进行访问;不可以修改该属性,因为修改相当于定义了一个新的同名的局部变量!
# 导入模块推荐顺序
import Python标准库模块
import Python第三方模块
import 应用程序自定义模块
# 导入模块中的指定属性 from-import
from module import name1, name2, ...
from module import * # 导入所有属性,不推荐
# 扩展import语句的as,取别名,方便理解和记忆
import module as XXX
from module import name1 as XXX
import numpy as np
import pandas as pd
# 重新导入自定义模块需要使用imp模块中的reload方法
from imp import reload
reload(module)

12.4 模块内建函数

系统为模块提供了一些功能上的支持。

# 1.__import__():实际上导入模块的函数
var = __import__(module_name) # 参数为字符串;返回值为对应的模块对象,所以需要将引用传给变量,否则无法使用该模块
sys = __import__('sys') # 等价于import sys 

# 2.globals()和locals():返回调用者全局和局部名称空间的字典的函数
# 在全局名称下,globals()和locals()返回相同的字典,因为此时的局部名称空间就是全局空间
def foo():
    print('calling foo()...')
    num = 123
    name = 'foo'
    print("foo()'s globals:", globals().keys())
    print("foo()'s locals:", locals().keys())
print("__main__()'s globals:", globals().keys())
print("__main__()'s locals:", locals().keys())
foo()

# 3.reload():重新导入模块需要使用imp模块中的reload方法
# 模块必须是全部导入(不是from-import),reload()函数的参数必须是模块自身而不是模块名字的字符串,reload()函数重新导入导致模块会执行
from imp import reload
reload(module)

12.5 包

包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用程序执行环境。Python1.5加入了包,用来帮助解决如下问题:

  • 为平坦的名称空间加入有层次的组织结构
  • 允许程序员把有联系的模块组合到一起
  • 允许分发这使用目录结构而不是一大堆混乱的文件
  • 帮助解决有冲突的模块名称
# 1.目录结构
# 导入包中的模块:from package.module import sub_module
# 模块下的__init__.py 文件,用于初始化模块。

# 2.使用from-import导入包:
# from package import * # 导入package.module下的所有模块(__all__变量中定义的)
# __init__.py 中的 __all__ 变量包含执行该语句时应该导入的模块名字符串列表。

# 3.绝对导入
# 所有的导入都被认为是绝对的,即这些被导入的模块必须通过Python路径(sys.path或是PYTHONPATH)来访问。

# 4.相对导入
from Phone.Mobile.Analog import dial # 绝对导入
from .Analog import dial # 相对导入
from ..Fax import G3.dial # 相对导入

12.6 模块的其他特性

  1. Python解释器在标准模式下启动时,一些模块会被解释器自动导入,用于系统相关操作。sys.modules变量包含一个由当前载入(完整且成功导入)到解释器的模块组成字典,模块名为键,对应的位置为值。
  2. 阻止属性导入。如果不想让某个模块属性被 from module import * 导入 ,可以在不想导入的属性名称加上一个下划线_。
  3. 不区分大小的导入。指定 PYTHONCASEOK 环境变量,以不区分大小写地导入模块。

12.7 相关模块

  • imp:这个模块提供了一些底层的导入者功能。
  • modulefinder:该模块允许你查找 Python 脚本所使用的所有模块。
  • pkgutil:该模块提供了多种把 Python 包打包为一个”包”文件(*.pkg)分发的方法。
  • site:和 *.pth文件配合使用, 指定包加入 Python 路径的顺序。
  • zipimport :使用该模块导入 ZIP 归档文件中的模块。
  • distutils:该模块提供了对建立、 安装、分发 Python 模块和包的支持。

参考资料:

  1. 《Python核心编程》学习笔记

你可能感兴趣的:(默认,Python,Python,模块)