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

时间:2010-10-11 18:40:12

标签: python import module

main.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和类无效:

main.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

但它将从main.py:def'打印'。 (在使用import时也可以。)

为什么这样工作?似乎导入subone后,subtwo可以使用print subone.a

这是因为导入的模块相互依赖而不经过“父”模块是不好的编程吗?还有另一种标准方法吗?

更新

我现在明白第一个示例不起作用,因为行subone无法识别名称subtwo,它不在 main.py 命名空间(即使它在subtwo中),它是从模块import subone内调用的。这可以通过使用subtwo.py顶部的subtwo来修复 - 它不会重新加载模块,但会将其添加到subtwo的命名空间,以便from subone import Nugget from subtwo import Wrap wrap = Wrap() print wrap.nugget.gold 可以用它。

但是这个怎么样:

main.py:

class Nugget:
    gold = 'def'

subone.py:

class Wrap:
    nugget = Nugget()

subtwo.py:

Wrap

我认为,因为Nuggetmain都直接加载到main的命名空间,所以他们会使用NameError: name 'Nugget' is not defined的命名空间并且能够引用彼此,但它会抛出一个Wrap。这是因为subtwo是在 main的命名空间中从评估/检查之前被加载到{{1}}的命名空间中吗?

5 个答案:

答案 0 :(得分:6)

如果您以这种方式修改了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”将“x”添加到当前模块   命名空间,而“from x import *”将   添加所有模块级属性   直接进入当前模块命名空间

所以在你上面的main.py,subone.py和subtwo.py的第一个例子中,main.py中的命名空间将包含'subone'和'subtwo',而subtwo.py将有一个空的命名空间和无法访问subone.a。

[编辑:更多解释] 考虑以下文件: main.py

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'

subtwo.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']
  

一些观察

  1. 您会注意到导入模块subtwo.py,会立即执行print语句。
  2. 因此,当在main.py中导入subone和subtwo时,main.py的命名空间会被扩充。
  3. 这并不意味着将增加subtwo的命名空间。所以“a”只能通过subone.a
  4. 在main.py中使用
  5. 当我们在subtwo.py中导入subone时,subwo的命名空间用subone增加,而subow.py中的module subone属性a可通过subone.a
  6. 获得。

答案 1 :(得分:3)

你能解释一下为什么你觉得subone应该可以用于subwo,当subone被main导入时?实际上,可以在不知道main.py导入了什么的情况下编译了subtwo.py。

另外,如果第二个程序导入了subtwo.py,那么subwo对subone的了解是否取决于导入subtwo的两个主程序中的哪一个?这会降低subtwo的可重用性。

看起来您正在考虑将编译作为具有已定义顺序的进程,累积状态信息:编译main.py,在此期间我们编译/导入subone.py,从中累积信息,然后我们编译/使用我们已经积累的信息导入subtwo.py。

相反,除非声明依赖关系,否则每个模块的编译都独立于其他模块。这使得重用和维护代码变得更加容易:隐藏的依赖性更少。

  

是不是因为编程不好   有进口模块取决于每个   其他没有通过他们的   '父母'模块?

不是这样......让模块2依赖于模块1 而不是这样,即没有模块2声明“我依赖于模块1”,这只是糟糕的编程。

答案 2 :(得分:2)

subtwo命名空间将完全为空,除非您将subone导入其中。

就编程实践而言,如果需要,subonesubtwo可以相互依赖,您只需要明确地链接它们(使用import

答案 3 :(得分:0)

关于你的第二个例子,“main.py”知道Nugget但“subtwo.py”不知道。

我认为以这种方式考虑会有所帮助。每个模块(文件)都必须像现有的其他模块一样工作。在这种情况下,“subtwo.py”将无法自行运行,因为它尚未导入Nugget。基本上“subtwo.py”不知道“main.py”知道什么。它不应该,因为它可以被任何人从任何地方调用,并且它不能依赖于其他任何人导入它所需要的东西。

答案 4 :(得分:0)

这是因为导入的模块有自己独立的命名空间。你写的非常像:

def func1():
    a = 1

def func2():
    print a

func1()
func2()  # This will throw an error

a = 2

func2()  # Now this will print 2.

模块在本地具有命名空间,当您使用from subone import *时,只将命名空间导入main.py命名空间,而subtwo无法访问该命名空间。

然而 - 你要做的是非常糟糕的做法。避免使用全局变量和import *,因为你会像现在一样越来越困惑。

更多信息: https://docs.python.org/3/reference/import.html

https://bytebaker.com/2008/07/30/python-namespaces/

http://www.diveintopython.net/html_processing/locals_and_globals.html

并且可能:http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html