鱼C论坛

 找回密码
 立即注册
查看: 2524|回复: 5

[已解决]第51课,执行a.py,b.py报错·,不明白为什么添加if __name__=='__main__'就可以了

[复制链接]
发表于 2020-8-27 22:43:20 | 显示全部楼层 |阅读模式

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

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

x
请问一下,在第51课课后习题中,执行a.py,b.py均会报错,添加if __name__=='__main__':就可以解决了,代码如下(已修正):程序报错是因为执行b.py文件之后过程如下:

执行 b.py -> import a -> 查找 a 模块 -> 未发现 a 模块对象 -> 导入 a.py -> import b -> 查找 b 模块 -> 发现 b 模块对象 -> 接着往下执行字节码(import a 已执行过,Python 有机制确保不重复导入,因而不会再执行) -> a.x() -> 在 a 模块中找不到 x(),因为 a 还没有被完全导入。

添加if __name__=='__main__':之后也就是把.py文件当成独立程序运行,会执行a.x(),如果是当成模块导入的时候不会执行

但是添加语句之后,在运行b.py()执行过程不还是像上边那样,最后到a.x(),找不到x报错吗?但事实是可以运行,请问这是为什么,添加if __name__=='__main__影响了哪里?

正确代码:
#a.py文件
import b

def x():
    print('x')

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



#b.py文件
import a

def y():
    print('y')

if __name__=='__main__':
    a.x()
最佳答案
2020-8-27 23:58:46
执行过程是这样子的,小甲鱼讲的并不是特别清楚
若没有 if __name__=='__main__': 这一句的话,执行过程如下,红色部分小甲鱼没有说,导致很多人不理解:
执行b.py -> import a -> 查找 a 模块 -> 未发现 a 模块对象 -> 导入 a.py -> import b -> 查找 b 模块 -> 发现 b 模块对象 -> 接着上次执行的位置往下执行字节码(import a 已执行过,Python 有机制确保不重复导入,因而不会再执行) -> 导入def y() -> 执行 a.x() -> 在 a 模块中找不到 x(),因为 a 还没有被完全导入。

若有if __name__=='__main__': 这一句的话,执行过程如下:
执行b.py -> import a -> 查找 a 模块 -> 未发现 a 模块对象 -> 导入 a.py -> import b -> 查找 b 模块 -> 发现 b 模块对象 -> 接着上次执行的位置往下执行字节码(import a 已执行过,Python 有机制确保不重复导入,因而不会再执行) -> 导入def y() -> 判断if __name__=='__main__' 发现__name__ == 'b',不执行下一句a.x(),b模块导入完成  -> 继续导入a模块,接着上次执行的位置往下执行字节码(import b 已执行过)-> 导入def x() -> 判断if __name__=='__main__' 发现__name__ == 'a',不执行下一句b.y(),a模块导入完成  -> 继续执行b模块,这时接上了第一个箭头后面的import a,然后定义 def y() (这里实际上是又定义了一遍该函数)-> 判断if __name__=='__main__' 发现__name__ == '__main__',执行下一句a.x()。

我修改了一下这两文件,添加了一些print,可以很直观的看到执行过程
  1. # a.py
  2. import b
  3. print('In a,__name__ is',__name__ )
  4. def x():
  5.     print('x')
  6. print('aa')
  7. if __name__ == "__main__":
  8.     b.y()

  9. # b.py
  10. import a
  11. print('In b,__name__ is',__name__ )
  12. def y():
  13.     print('y')
  14. print('bb')
  15. if __name__ == "__main__":
  16.     a.x()
复制代码

运行结果如下
  1. In b,__name__ is b
  2. bb
  3. a a
  4. aa
  5. In b,__name__ is __main__
  6. bb
  7. x
复制代码

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-8-27 23:58:46 | 显示全部楼层    本楼为最佳答案   
执行过程是这样子的,小甲鱼讲的并不是特别清楚
若没有 if __name__=='__main__': 这一句的话,执行过程如下,红色部分小甲鱼没有说,导致很多人不理解:
执行b.py -> import a -> 查找 a 模块 -> 未发现 a 模块对象 -> 导入 a.py -> import b -> 查找 b 模块 -> 发现 b 模块对象 -> 接着上次执行的位置往下执行字节码(import a 已执行过,Python 有机制确保不重复导入,因而不会再执行) -> 导入def y() -> 执行 a.x() -> 在 a 模块中找不到 x(),因为 a 还没有被完全导入。

若有if __name__=='__main__': 这一句的话,执行过程如下:
执行b.py -> import a -> 查找 a 模块 -> 未发现 a 模块对象 -> 导入 a.py -> import b -> 查找 b 模块 -> 发现 b 模块对象 -> 接着上次执行的位置往下执行字节码(import a 已执行过,Python 有机制确保不重复导入,因而不会再执行) -> 导入def y() -> 判断if __name__=='__main__' 发现__name__ == 'b',不执行下一句a.x(),b模块导入完成  -> 继续导入a模块,接着上次执行的位置往下执行字节码(import b 已执行过)-> 导入def x() -> 判断if __name__=='__main__' 发现__name__ == 'a',不执行下一句b.y(),a模块导入完成  -> 继续执行b模块,这时接上了第一个箭头后面的import a,然后定义 def y() (这里实际上是又定义了一遍该函数)-> 判断if __name__=='__main__' 发现__name__ == '__main__',执行下一句a.x()。

我修改了一下这两文件,添加了一些print,可以很直观的看到执行过程
  1. # a.py
  2. import b
  3. print('In a,__name__ is',__name__ )
  4. def x():
  5.     print('x')
  6. print('aa')
  7. if __name__ == "__main__":
  8.     b.y()

  9. # b.py
  10. import a
  11. print('In b,__name__ is',__name__ )
  12. def y():
  13.     print('y')
  14. print('bb')
  15. if __name__ == "__main__":
  16.     a.x()
复制代码

运行结果如下
  1. In b,__name__ is b
  2. bb
  3. a a
  4. aa
  5. In b,__name__ is __main__
  6. bb
  7. x
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 3 反对 0

使用道具 举报

 楼主| 发表于 2020-8-28 00:10:01 | 显示全部楼层
sunrise085 发表于 2020-8-27 23:58
执行过程是这样子的,小甲鱼讲的并不是特别清楚
若没有 if __name__=='__main__': 这一句的话,执行过程如 ...

明白了,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-4-16 17:33:00 | 显示全部楼层
sunrise085 发表于 2020-8-27 23:58
执行过程是这样子的,小甲鱼讲的并不是特别清楚
若没有 if __name__=='__main__': 这一句的话,执行过程如 ...

大牛啊,分析的明明白白,太感谢了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-16 11:10:15 | 显示全部楼层
sunrise085 发表于 2020-8-27 23:58
执行过程是这样子的,小甲鱼讲的并不是特别清楚
若没有 if __name__=='__main__': 这一句的话,执行过程如 ...

谢谢! 终于理解了!
厉害,真正把整个过程都写出来了。
刚开始看小甲鱼的没看明白,因为他漏了一些后续的执行过程。
一开始我没搞懂为什么x还是被打印出来了?
噢,原来是导入完a,b模块之后,要回到b上次执行的位置,继续执行b.py里面的代码。由于b是主程序,所以可以执行a.x()。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-4 17:56:23 | 显示全部楼层
a a 那里应该是In a,__name__ is a吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-3-29 00:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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