最近又听了一些关于Python倒包的视频。
写一些自己的感想与笔记,Python是一个oop编程的语言,思想中包含着,万物皆对象的逻辑。
所以很显然,模块也是一个对象。而且按照Python的对象三层设计,type创建类对象,类对象创建实例对象。
通过测试,模块属于最底层的实例层级,是通过module的类创建的。
所以假如通过 import mymodule的时候,当sys.module里面不存在这个模块的时候,Python会在sys.path的路径中去寻找是否存在mymodule.py的文件。
当存在这个文件的时候,首先Python会创建一个mymodule的module的实例,然后逐条执行该module的指令,给该实例进行属性复制。
所以主要你只是循环倒包,不要通过from module import attr 的方式去读取一个模块的属性的时候,无论你如何循环,Python运行是不存在问题的。
因为Python对倒包进行了优化,只要倒入了一次,那sys.module里面就会存在该模块的映射,如果你再import该模块的时候,会直接从该映射中读取,不会再去执行该py文件。
最后文字描述两个倒包的案例。
a.py
import b
b. py
import a
就这样所谓的循环,不会造成任何问题,只不过代码像一坨屎。
如果执行a.py,整个逻辑如下,遇到import b 会首先去sys.modules里面找是否存在该模块,不存在。就再sys.path中找b.py的文件,找到了,首先创建一个b的空模块对象,
然后逐条执行b.py文件,给空的b对象赋值属性。所以执行b.py的时候,执行到import a 又会到sys.modules取查找a模块对象,找不到,创建一个a的空模块对象,执行a.py的文件。
执行a.py的过程中,第一句又是Import b,这个时候,b的模块已经有了,就是第一次倒入的空对象,在sys.modules里面,所以不会再取找b.py的文件。所以就不存在a.py文件的import b命令又去执行b.py导致死循环的情况,等a.py读取完毕,那b.py的import a 执行就执行完毕了,那整个b.py也执行完毕了,就返回到了第一层a.py的import b 处,整个倒包执行完毕。
这个互相倒包的过程中,就a.py内的指令被执行了两次,第一次是执行a.py的时候,当普通Python脚本运行的时候,第二次是当被其它脚本当做模块时候。
但运行的时候,环境发生了变化,也就是sys.module,所以执行import的语句的时候,具体的执行也就发生了变化。
如果理解了这个,第二个错误的案例我就不上了,理论上,我们要尽量避免循环倒包的出现,但实际测试只要加好了
if __name__ == '__main__'问题也不大,哈哈哈, 那些要执行的命令都放在这个下面就好了,可以避免多次执行。
重点的重点,模块是由模块类创建的,刚开始创建的是一个没有任何属性的对象,逐条读取模块内的赋值语句才会对该对象进行属性赋值。
理解了这个,倒包就不应该出问题了。