前一段时间,在猿编程讲师岗前培训中,有学员问到在pgzero里面,为什么 import pgzrun 之后,music、mouse、keyboard这些模块就能自动加载,不需要import,就能直接使用了。于是我看了一下源码,最核心的代码是这两句,摘录如下:

mod = sys.modules['__main__']
mod.__dict__.update(builtins.__dict__)  # builtins 模块中引用了music等模块

以上代码中,有一个关键的方法,就是sys.modules。sys.modules是一个全局字典,该字典是python启动后就加载在内存中。当导入新的模块时,sys.modules都将记录这些模块。字典sys.modules对于加载模块起到了缓冲的作用。当某个模块第一次导入,字典sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。

理解以上的解释之后,我们再看一个例子:

import sys
mod = sys.modules['__main__']
mod.__dict__.update({'aa':'bb'})
print(aa)   # 此处能输出bb

以上代码相当于把 aa:bb 这个键值对,添加到了sys模块中,而sys模块是提供对解释器使用或维护的一些变量的访问,像我们定义变量,其实也可以通过sys拿到,那么以上的 update 方法,等同于定义了变量aa='bb',所以打印aa可以得到bb的值。

接下来,我们再看一下如何实现模块自动加载,依次定义如下文件。

# main.py
import sys
import autoload

mod = sys.modules['__main__']
mod.__dict__.update(autoload.__dict__)
print(a.add(1,2))  # 输出3
print(b.div(1,2))  # 输出0.5
# autoload.py
import a
import b
# a.py
def add(num1, num2):
   return num1 + num2
# b.py
def div(num1, num2):
   return num1 / num2

以上例子中,main.py 只引入了 autoload 模块,而在 autoload 中引入a、b两个模块。因为 main.py 文件中有 mod.__dict__.update() 操作,从而实现了 a、b两个模块的自动加载,就这。

本文为 陈华 原创,欢迎转载,但请注明出处:http://www.ichenhua.cn/read/214