在以下代码中,无论执行a.py还是b.py,都会报错。

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

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

#在a.py中运行,产生的报错内容如下
Traceback (most recent call last):
  File "D:\python\a.py", line 1, in <module>
    from b import y
  File "D:\python\b.py", line 1, in <module>
    from a import x
  File "D:\python\a.py", line 1, in <module>
    from b import y
ImportError: cannot import name 'y'

从报错提示中我们可以看出,a.py执行到"from b import y"时会跳转到b.py模块中,为了在b.py中找到y函数,解释器会自上而下的一行一行执行,当在b.py中执行到"from a import x"时又会跳转到a.py模块中进行搜索,如此循环反复,陷入死循环导致报错。

-----------------------------------------------------------------------------------------

我们尝试下对代码进行修改,将"from (模块) import (函数)" 改为"import (模块)",如下所示:

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

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

结果发现,无论在a.py还是在b.py中运行,解释器都没有报错。而我若在a.py中运行,只需要b.y()便可正确访问b.py下的y函数。当我再进一步的做尝试,如下代码所示(在a.py中运行):

>>> b.y()
y
>>> b.a.b.a.b.a.b.a.b.a.b.a.b.y()
y
>>> x()
x
>>> b.a.x()
x
>>> b.a.b.a.b.a.b.a.b.a.x()
x

可以看出,解释器都作出了正确的访问。

因此,不难得出结论:解释器对①"import (模块)"和②"from (模块) import (函数)"的解释方式是不同的。

以a.py做执行模块为例:

①的解释方式为:直接将b.py中的代码导入a.py中,并将来自b.py模块中的元素(包含函数、类、变量等)的名字前加上"b."以作为区分。

而②的解释方式为:前往b.py中寻找所需要导入的函数,而这个过程需要一行一行的找,遇到需要访问其他文件或模块的代码,就乖乖地去访问(可以理解为见缝就钻),拼命的找!疯狂的找!只有找到才肯罢休,否则会把指定的模块的代码一行一行的搜个遍。