鱼C论坛

 找回密码
 立即注册
查看: 2795|回复: 9

关于import导入的另外一点疑问

[复制链接]
发表于 2015-12-18 01:42:52 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 zhang77595103 于 2015-12-18 10:29 编辑

如图,前一个是错误的代码 第二个是小甲鱼的解释, 说实话越看越迷糊,  就是搞不清具体运行b.py之后导入import a 然后 a.py里面又要import b, 这不是无限循环了?
screenshot.png
screenshot.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2015-12-18 11:59:52 | 显示全部楼层
所以这样做是错误的。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-18 13:14:04 | 显示全部楼层
本帖最后由 zhang77595103 于 2015-12-18 13:15 编辑
wei_Y 发表于 2015-12-18 11:59
所以这样做是错误的。



一开始从b.py开始执行, 然后碰到import a, 查找a模块对象,未找到 然后去导入a模块(问题1:导入的过程是不是就是预处理a.py)
如果是:
预处理a.py导入过程中:碰到import b, 查找b模块对象发现已经存在(我们一开始就是从b.py开始的)
问题2: 发现b模块已经存在之后, 我个人认为应该直接跳过import b这一句 直接就继续向下执行,所以印发的错误的地方应该是在a.py最后的b.y()
但是按照小甲鱼的解释:虽然发现b模块已经导入,编译器仍然返回到了b.py,然后开始往下执行。如果这样的话,模块导入与否都要重新导入,检查是否导入的意义在哪里?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-18 18:35:21 | 显示全部楼层
本帖最后由 wei_Y 于 2015-12-18 18:37 编辑
zhang77595103 发表于 2015-12-18 13:14
一开始从b.py开始执行, 然后碰到import a, 查找a模块对象,未找到 然后去导入a模块(问题1:导入的 ...


导入某模块时先检测有没有相应的pyc文件,没有的话会先生成一个。

在b中导入a时,a中又要导入b才行,那么现在又回到了b,但是a并没有导入全,因为a只执行到import b。
在b中又需要导入a,但此时sys.modules中存在a已被导入的记录,(所以不会造成循环。)所以直接跳过import a执行b以下的程序。
那么也就是b只导入了 a中import b这一条语句。那么a中剩余的其他语句就一个也没被加载到b上。

这个过程你只需要把a中import b放到所有语句的最后面,就可以看到。

栗子:
c.py
  1. import b

  2. def x():
  3.         return '7'
复制代码

b.py
  1. import c

  2. print(c.x())
复制代码

运行b就会报错。
  1. AttributeError: module 'c' has no attribute 'x'
复制代码

此报错不是由我们运行的b所发,是由c.py文件中导入b所发。

修改一下c.py
  1. def x():
  2.         return '7'

  3. import b
复制代码

  1. 7
  2. 7
  3. >>>
复制代码

没有报错,运行b时调用了一个c.x(),导入c时又会导入一遍b则又调用一个c.x(),因为c已存在于sys.modules中所以循环到这里就结束了。

有点啰嗦,希望有帮助~。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2015-12-18 20:48:18 | 显示全部楼层
wei_Y 发表于 2015-12-18 18:35
导入某模块时先检测有没有相应的pyc文件,没有的话会先生成一个。

在b中导入a时,a中又要导入b才行 ...

解答很详细,已经弄懂了,非常感谢!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-11-1 09:29:13 From FishC Mobile | 显示全部楼层
改过后为什么会执行两遍?在b中不应该只执行一下 已经是返回b的结果了吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-11-1 10:17:27 | 显示全部楼层
很简单import本身不会多次导入一个模块。
当已经导入了一个模块a的时候,第二次导入模块a不会被导入
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-13 17:04:18 | 显示全部楼层
关键在于import语句是否执行完毕,其实用纸笔画个图,逻辑会比较清晰。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-13 17:22:50 | 显示全部楼层
谦虚 发表于 2017-11-1 09:29
改过后为什么会执行两遍?在b中不应该只执行一下 已经是返回b的结果了吗?

运行逻辑,执行b.py,有两个小步骤:
①import c
②print语句

其中,步骤①import c,相当于调用c.py。所以类似于调用函数先跳进去,等执行完再回到步骤②。
所以:
①import c可以划分成以下语句,在c.py执行:
   ⑴def x()语句    #此处没有执行函数,所以无输出。
   ⑵import b   

此时,执行⑵import b又可以分为以下语句执行:
Ⅰ import c   #之前已经导入到sys.modules里面,不会重新导入。
Ⅱ print语句,输出‘7’

执行完上述语句后,回到最初的②print语句,打印‘7’。

所以总共输出两次。
其实在纸上画个树状图展开一下,就更清晰了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-23 08:37:34 From FishC Mobile | 显示全部楼层
payton24 发表于 2017-12-13 17:22
运行逻辑,执行b.py,有两个小步骤:
①import c
②print语句

很清晰易懂   感谢回复
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-18 19:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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