封闭式导入如何在python中工作

How enclosed import works in Python

本问题已经有最佳答案,请猛点这里访问。

这是我在皮硫磷的进口产品中搞不清楚的。假设我有一个模块"a",它用"import b"导入模块"b"。然后,有一个模块"c"导入模块"a"。模块"b"的名称是否在"c"中可用?

我已经检查过它实际上取决于您如何在模块"c"中导入模块"a"。如果您执行"导入A",则"B"中的名称在"C"中不可用。但是,如果您执行"从导入*",则它们将可用。有人能解释一下区别吗?


如果你仔细考虑这些命令的实际作用,那就非常简单了。

A.PY:

1
2
import b
foo = 0

B.PY:

1
bar = 1

C.Py:

1
import a

c开始,你不能只说foo,你必须说a.foo。对于a中的每个名称(常量、变量、函数、类甚至模块)也是如此。其中包括b

所以,你不能说bara.bar,但你可以说a.b.bar

现在,如果你这样改变它会怎么样:

A.PY:

1
2
from b import *
foo = 0

B.PY:

1
bar = 1

C.Py:

1
from a import *

from b import *所做的就是把b的名称空间中的所有内容都取出来,放到a的名称空间中,这样就可以直接从a中说bar。然后,当你做from a import *的时候,它把a的名称空间中的所有东西都放在c的名称空间中,就像你做foo一样,你也可以做bar

这就是为什么除了顶级脚本之外,您通常不想在任何地方执行from b import *,因为您的名称空间都被合并在一起。

这也是为什么你可以限制*__all__所得到的东西:

A.PY:

1
2
3
from b import *
__all__ = ['foo']
foo = 0

B.PY:

1
bar = 1

C.Py:

1
from a import *

现在,从c开始,你可以做c.foo,但不能做c.bar

因此,a可以做from b import *来实现自己的特性,而不需要向用户公开b的所有内部。


import语句导致执行模块,所有变量都保存在执行模块的命名空间中。也就是说,如果你是import a,那么a的所有变量都将在a.[variable]下。from关键字给出的行为略有不同:它将变量放在当前命名空间中。例如,from a import foo将变量foo放入当前名称空间。from a import *a中的所有变量导入当前命名空间。as关键字允许您在导入变量时对其进行重命名;因此,from a import foo as bar允许您访问a.foo,但必须称之为barimport a.foo as foo相当于from a import foo


比上面更具体的例子:

a.py

1
2
import b
bar = 'bar'

b.py

1
foo = 'foo'

c.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import a


try:
   print(b.foo)
except:
   print('No `b` in current namespace')

try:
   print(a.bar)
except:
   print('No `a` in current namespace')

try:
   print(a.b.foo)
except:
   print('No `a` or `a.b` in current namespace')

打印顺序如下:

1
2
3
No `b` in current namespace
bar
foo

换句话说,b通过a可用,但只能通过访问a的命名空间