gpt4 book ai didi

Python:为什么导入的模块不能引用另一个导入的模块?

转载 作者:太空狗 更新时间:2023-10-29 18:29:13 25 4
gpt4 key购买 nike

ma​​in.py:

import subone
import subtwo

subone.py:

a = 'abc'

subtwo.py:

print subone.a

运行 python main.py 会抛出一个 NameError: name 'subone' is not defined。我希望它打印“abc”。

重构它以使用 from import 和类没有帮助:

ma​​in.py:

from subone import *   # Only using from X import * for example purposes.
from subtwo import *

print 'from main.py:', a.out

subone.py:

class A:
out = 'def'

a = A()

subtwo.py:

# This throws NameError: name 'a' is not defined
print a.out

# This throws NameError: name 'A' is not defined
b = A()
print b.out

但是它打印'from main.py: def'。 (它在使用 import 时也有效。)

为什么会这样?似乎一旦 subone 被导入,它应该对 subtwo 可用。

是不是因为让导入的模块相互依赖而不通过它们的“父”模块是糟糕的编程?是否有另一种标准方法可以做到这一点?

更新:

我现在明白第一个示例不会工作,因为行 print subone.a 无法识别名称 subone,它不在 subtwo 命名空间(即使它在 main.py 中),并且它是从模块 subtwo 中调用的.这可以通过在 subtwo.py 顶部使用 import subone 来解决——它不会重新加载模块,但会将其添加到 subtwo 的命名空间,以便 subtwo 可以使用它。

但是这个呢:

ma​​in.py:

from subone import Nugget
from subtwo import Wrap

wrap = Wrap()
print wrap.nugget.gold

subone.py:

class Nugget:
gold = 'def'

subtwo.py:

class Wrap:
nugget = Nugget()

我认为,由于 WrapNugget 都直接加载到 main 的命名空间中,因此它们将使用 main 的命名空间并能够相互引用,但它抛出一个 NameError: name 'Nugget' is not defined。是因为 Wrap 在加载到 main 的命名空间之前,是从 subtwo 的命名空间中评估/检查的?

最佳答案

如果你以这种方式修改你的 subtwo.py 那么它会工作

import subone
print subone.a

当您在 subtwo.py 中执行 subone.a 时,您试图访问 subtwo.py 中的命名空间 subone,在命名空间“subone”中,应该有一个属性“a”。

当你这样做时 - 在 subtwo.py 中导入 subone,然后 subone 被添加到命名空间并且 subone 命名空间具有属性 a。所以 subone.a 会起作用。

我还建议您使用 dir() 来了解如何添加命名空间。

在 subtwo.py 中,您可以执行以下操作:

print dir()
import subone
print dir()
print subone.a

同样,尝试在导入语句前后添加“print dir()”,您应该会清楚这个想法。

"import x" adds 'x' to the current modules namespace while "from x import * " will add all the module level attributes directly into current module namespace

所以在上面的第一个 main.py、subone.py 和 subtwo.py 示例中,main.py 中的命名空间将包含“subone”和“subtwo”,而 subtwo.py 将有一个空命名空间,并且无法访问 subone.a。

[编辑:更多解释]考虑以下文件:主程序

print "Before importing subone : ", dir()
import subone
print "After importing subone and before importing subtwo: ", dir()
import subtwo
print "After importing subone and subtwo: ", dir()

subone.py

a = 'abc'

子二.py

print dir()
import subone
print "module level print: ", subone.a
print dir()
def printX():
print subone.a

以及运行 main.py 的输出:

Before importing subone :  ['__builtins__', '__doc__', '__file__', '__name__', '__package__']
After importing subone and before importing subtwo: ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'subone']
['__builtins__', '__doc__', '__file__', '__name__', '__package__']
module level print: abc
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'subone']
After importing subone and subtwo: ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'subone', 'subtwo']

Some Observations

  1. 您会注意到导入模块 subtwo.py 后,打印语句会立即执行。
  2. 所以当 subone 和 subtwo 在 main.py 中导入时,main.py 的命名空间被扩充了。
  3. 这并不意味着 subtwo 的命名空间会被扩充。所以“a”仅在 main.py 中通过 subone.a 可用
  4. 当我们在 subtwo.py 中导入 subone 时,subtwo 的命名空间会增加 subone 并且模块 subone 的属性 a 可以通过 subone.a 在 subtow.py 中使用

关于Python:为什么导入的模块不能引用另一个导入的模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3909002/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com