鱼C论坛

 找回密码
 立即注册
查看: 2350|回复: 10

import 导入过程中的执行顺序问题

[复制链接]
发表于 2018-4-30 16:13:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #a.py
  2. import b
  3. print('hello')
  4. def x():
  5.         print('x')

  6. if __name__ == '__main__':
  7.         b.y()
复制代码

  1. #b.py
  2. import a
  3. print('world')
  4. def y():
  5.         print('y')
  6. print('!')
  7. if __name__ == '__main__':
  8.         print('1')
  9.         a.x()
复制代码


运行b.py,输出如下:
  1. world
  2. !
  3. hello
  4. world
  5. !
  6. 1
  7. x
复制代码

输出的前两个我能理解,执行b.py(生成模块对象b)->import a -> 未发现a模块 -> 导入a.py(生成模块a) -> import b -> 存在b模块 -> 执行b模块字节码 ->  输出world -> 输出'!'......
后面就不懂了。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-4-30 16:18:39 | 显示全部楼层
从输出可以看出a 模块完全被导入是发生在b 模块if __name__ == 'main'时,
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-30 20:37:34 | 显示全部楼层
测试了一下,它的运行顺序似乎是:执行b.py的import a 打印"world"和"!"之后把导入进来的a.py if __name__ == '__main__' 之上的print('hello')这行语句执行了一遍当然这里有点绕脑,因为此时a.py也导入了b.py所以呢,a.py又把b.py的print('world')和print('!')执行一遍之后才执行最后的if __name__ == '__main__':打印了最后的1 和 ‘x’ 这是我的测试的结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-4-30 20:59:24 | 显示全部楼层
Sanks 发表于 2018-4-30 20:37
测试了一下,它的运行顺序似乎是:执行b.py的import a 打印"world"和"!"之后把导入进来的a.py if __name__  ...

搞不懂为什么在b模块中执行到 if __name__ == '__main__'的时候会自动完全导入a模块,然后又重新执行一遍b模块
  1. #a.py
  2. import b
  3. print('hello')
  4. def x():
  5.         print('x')

  6. if __name__ == '__main__':
  7.         b.y()

  8. print('a完全被导入')
复制代码
  1. #b.py
  2. import a
  3. print('world')
  4. def y():
  5.         print('y')
  6. print('!')
  7. if __name__ == '__main__':
  8.         print('1')
  9.         a.x()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-30 22:40:36 | 显示全部楼层
本帖最后由 ABC23 于 2018-4-30 22:44 编辑

#a.py
import b
print('hello')
def x():
        print('x')

if __name__ == '__main__':
        b.y()

#b.py
import a
print('world')
def y():
        print('y')
print('!')
if __name__ == '__main__':
        print('1')
        a.x()

运行结果:

world
!
hello
world
!
1
x

====================
一步一步看,应该不难理解。
因为运行的是模块b,所以我们以b为主考虑。

1. 先看全局的语句,打印world和!;
2. 在看函数,函数是Python的一等公民。它不直接加载,而是等到运行时加载;等着。
3. 看if __name__ == '__main__'这一行,这行语句表示【当该模块作为主模块运行时加载以下语句】,这里就是b模块;
4. 因为我们在b的头部import了模块a,在执行玩b的全局语句后执行a的全局语句,打印hello;
5. 要导入的模块(依赖的模块)之前已经加载完毕,接着会运行if __name__ == '__main__'下面的语句,打印1、x
6. 回头看3,b模块的函数自始至终没有被执行,那就不管她

要注意的是,import语句表示【必要时进行导入】,如果已经导入多了就不必重复导入。这应该是你理解的困境(我猜)。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-5-1 09:54:30 | 显示全部楼层
ABC23 发表于 2018-4-30 22:40
#a.py
import b
print('hello')

原来是要执行完b的全局语句后才执行import a ,我以为是先import a。但是为什么又再一次输出了'world'和'!'
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-5-1 10:48:35 | 显示全部楼层
Cczhou 发表于 2018-5-1 09:54
原来是要执行完b的全局语句后才执行import a ,我以为是先import a。但是为什么又再一次输出了'world'和' ...


不是的不是的。不是先执行玩b的全局语句导入a。
【代码是执行顺序总是和书写顺序保持一致(如果没有中断、跳转的话)】

举个例子你就懂了:
在桌面写两个py文件,a的全局语句print('I am a...')
在b的首行写:import a
b就一个全局语句print('I am the global statement from b...')

现在执行b模块为主模块,输出:
I am a...
I am the global statement from b...

但是如果你在b中这样写:
print('I am the global statement from b...')
import a
输出:
I am the global statement from b...
I am a...
懂了吗。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2018-5-1 11:25:40 | 显示全部楼层
ABC23 发表于 2018-5-1 10:48
不是的不是的。不是先执行玩b的全局语句导入a。
【代码是执行顺序总是和书写顺序保持一致(如果没有中 ...

哦哦。这个懂了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-5-1 14:14:16 | 显示全部楼层
Cczhou 发表于 2018-4-30 20:59
搞不懂为什么在b模块中执行到 if __name__ == '__main__'的时候会自动完全导入a模块,然后又重新执行一遍 ...

因为a模块也导入了b模块,当b模块执行a模块的时候执行了a模块中的代码(当然也包括a模块中调用的b模块),if __name__ == '__main__'除外,其实就这个执行顺序,你可以去掉些多余的打印代码去试试看。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-5-1 14:23:40 | 显示全部楼层
主要是比较绕,执行b的时候同时执行a而a又执行b,就这个顺序。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

发表于 2018-6-22 12:45:54 | 显示全部楼层
Cczhou 发表于 2018-4-30 20:59
搞不懂为什么在b模块中执行到 if __name__ == '__main__'的时候会自动完全导入a模块,然后又重新执行一遍 ...

因为a模块导入了b模块,所以b模块会重新执行一遍,执行完了之后到了if __name__=='__main__'也就是初始的代码b.py开始执行了,才会有剩下的效果,你可以删减点代码或者把if __name__ == '__main__'去掉再试试。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-12-29 20:55

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表