阅读本文大概需要 10 分钟。
提要
哈喽,大家好!继续分享我整理的一些Python3笔记
。
TL;DR
* 模块和包
一、模块
模块是最高级别的程序组织单元,它将程序代码和数据封装起来以便再利用,同时提供自包含的命名空间从而避免程序出现变量名冲突。
- import:以一个整体获取一个模块
- from:从一个模块文件中获取特定的名称
- imp.reload:在不终止 Python 程序的情况下重新载入模块文件代码的方法
# main.py
import webj2eedev
webj2eedev.sayhello()
# webj2eedev.py
def sayhello():
print('hello webj2eedev.')
1.1. 模块搜索路径
Python 的自动模块搜索路径(sys.path)包括:
- 程序的主目录
- PYTHONPATH目录(如果设置了的话)
- 标准库目录
- 任何 .pth 文件中的内容(如果存在的话)
- 第三方扩展应用的 site-packages 主目录
import sys
print('\n'.join(sys.path))
1.2. 模块的使用
- from * 语句:把模块中的所有名称复制到了进行导入的作用域中。
- 模块的导入只发生一次:模块会在第一次 import 或 from 时被载入并执行,并且只在第一次是如此。
- import 和 from 是可执行的语句,而不是编译时的声明。
- import 和 from 都是隐式的赋值语句。
- 通过名称字符串动态载入模块
- 直接通过 import 'XYZ' 是不行的
- 可以通过 exec 动态执行代码实现(exec 会在当前作用域中运行代码)
- 可以通过 Python 的官方机制:importlib.import_module 实现
- 小心递归形式的 from
- 注:如果无法完全断开循环,就应使用 import 和属性点号运算(而不是 from 和直接变量名)来推迟模块名称的访问,或者要么在函数内部(而不是在模块顶层),要么在文件底部附近运行from语句,以延迟 from 语句的执行。
- 技巧:__name__ 和 __main__
- 如果文件作为顶层程序文件执行,在启动时 __name__ 就会被设置为字符串 '__main__'
- 如果文件被导入, __name__ 就会改设为客户程序所了解的模块名。
- 通过这种技巧,我们可以让代码扮演两种不同的角色:作为工具的库模块,或是作为可执行的程序(例如:测试场景)。
- 技巧:通过 _X 形式隐藏数据
- 可以在名称前面加上一个下划线(例如:_x),从而防止客户程序使 from * 语句导入模块名时,把这些加下划线的名称复制出来。
- 注意:下划线不是“私有”声明:仍然可以通过其他形式的导入来获取并修改这类名称。
1.3. 模块命名空间
- 模块就是命名空间,存在于一个模块内的名称被称为模块对象的属性。
- 模块命名空间可以通过属性 __dict__ 或 dir() 获取。
- 模块是一个独立的作用域。
1.4. reload
- 当模块第一次在进程中被导入时(通过 import 或 from 语句),才加载和执行该模块的代码。
- 之后的导入只会使用已加载的模块对象,而不会重新加载或重新执行文件的代码。
- reload 函数会强制已加载模块的代码重新载入并重新执行。
reload 的目的是为了实现动态定制化,允许再整体程序不停止的情况下修改程序的一部分。
- reload 会影响所有使用 import 读取了模块的用户程序。因为使用 import 的用户程序需要通过点号运算符取出属性,在重新加载后,它们会发现模块对象中变成了新的值。
- reload 只会对以后使用 from 的用户程序造成影响。之前使用 from 来读取属性的用户程序并不会受到重新加载的影响,那些用户程序引用的依然是重新加载前所取出来的旧对象。
- reload 只适用于单一模块,不会自动递归地把模块的模块也自动加载。
二、模块包
- 模块导入,除了模块名之外,导入还可以指定目录路径。
- Python 代码的目录被称为包,因此这样的导入就称为包导入。
- 包导入是把计算机上的目录变成另一个 Python 命名空间,其属性则对应于目录中所包含的子目录和模块文件。
参考:
《Python学习手册 原书第五版 上册》