当你直接运行 python 脚本时,就像你正在做的那样python a.py
,python 解释器不会猜测该文件的模块路径应该是什么;它只是创建一个名为__main__
并运行它的模块。
另一个微妙之处在于,每次 python 遇到导入时,它首先创建模块并将其存储在其中,sys.modules
以便同一模块的所有其他导入生成相同的模块对象。只有留下面包屑后,它才会开始执行实现该模块的 python 代码。
所以这就是发生的事情,一步一步,你python a.py
在你的shell控制台输入,python创建一个__main__
模块并开始评估那个文件。
the file being parsed
|
| the module being imported
| |
./a.py __main__ 1: import b
好的,所以发生的第一件事就是a.py
导入一些东西。它以前从未导入过,因此它搜索路径并找到b.py
;由于我们仍在尝试导入另一个文件,因此我将缩进一点以显示这一点。
./b.py b 1: from a import orig
发生的第一件事b.py
是它尝试导入a
. 但a
也从未进口过;当python搜索路径时,它发现a.py
./a.py a 1: import b
看起来很熟悉; 但 b已被导入;这b
将是同一个(仍在导入过程中!
./a.py a 2: class orig:
./a.py a 3: def test(self):
./a.py a 4: print("hello")
./a.py a 5:
./a.py a 6:
./a.py a 7: o = orig()
./a.py a 8: o.a()
行。一个类被创建,实例化,并出现一些输出; a
现在已完成导入;这很好,因为b
使用了 from 导入,这意味着orig
现在需要存在,否则导入将失败。
./b.py b 2: orig.test=lambda self: print("wrong")
b
猴子补丁a.orig
(注意;不是__main__.orig
)。 b
现在也完成了导入。
./a.py __main__ 2: class orig:
./a.py __main__ 3: def test(self):
./a.py __main__ 4: print("hello")
./a.py __main__ 5:
./a.py __main__ 6:
./a.py __main__ 7: o = orig()
./a.py __main__ 8: o.a()
现在__main__
正在定义一个类,实例化它并打印一些输出。另请注意,这是 class 的定义__main__.orig
,而不是a.orig
b 修改的。
希望这能消除一些困惑。