简体   繁体   English

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

[英]Python: why can't an imported module reference another imported module?

main.py: main.py:

import subone
import subtwo

subone.py: subone.py:

a = 'abc'

subtwo.py: subtwo.py:

print subone.a

Running python main.py throws a NameError: name 'subone' is not defined . 运行python main.py会引发NameError: name 'subone' is not defined I expected it to print 'abc'. 我希望它打印'abc'。

Refactoring it to use from import and classes doesn't help: 重构它以from import和类中使用并没有帮助:

main.py: main.py:

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

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

subone.py: subone.py:

class A:
    out = 'def'

a = A()

subtwo.py: 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

BUT it will print 'from main.py: def'. 但它 “从main.py:高清”打印。 (It works when using import too.) (它在使用import也有效。)

Why does it work this way? 为什么这样工作? It seems like once subone is imported, it should be available to subtwo . 似乎一旦导入subone ,它应该可用于subtwo

Is it because it's bad programming to have imported modules depend on each other without going through their 'parent' module? 这是因为导入的模块相互依赖而不通过“父”模块是不好的编程? Is there another, standard way to do this? 还有另一种标准方法吗?

Update: 更新:

I now understand that the first example will not work because the line print subone.a doesn't recognize the name subone , it not being in subtwo 's namespace (even though it's in main.py 's), and it is being called from within the module subtwo . 我现在明白第一个例子不起作用,因为行print subone.a不识别名称subone ,它不在subtwo命名空间中(即使它在main.py ),并且它被调用从模块subtwo This can be fixed by using import subone at the top of subtwo.py -- it will not re-load the module but will add it to subtwo 's namespace so subtwo can use it. 这可以通过使用import subone顶部的import subonesubtwo.py - 它不会重新加载模块,但会将它添加到subtwo的命名空间中,因此subtwo可以使用它。

But what about this: 但是这个怎么样:

main.py: main.py:

from subone import Nugget
from subtwo import Wrap

wrap = Wrap()
print wrap.nugget.gold

subone.py: subone.py:

class Nugget:
    gold = 'def'

subtwo.py: subtwo.py:

class Wrap:
    nugget = Nugget()

I would think that since Wrap and Nugget are both loaded directly into main 's namespace, that they would use main 's namespace and be able to reference each other, but it throws a NameError: name 'Nugget' is not defined . 我认为既然WrapNugget都直接加载到main的命名空间中,那么它们将使用main的命名空间并能够相互引用,但它会引发NameError: name 'Nugget' is not defined IS IT because Wrap is evaluated/checked from within subtwo 's namespace BEFORE being loaded into main 's namespace? 是不是因为Wrap评估/从内部检查subtwo的命名空间前,加载到main的命名空间?

If you modified your subtwo.py this way then it will work 如果您以这种方式修改了subtwo.py,那么它将起作用

import subone
print subone.a

When you do subone.a in subtwo.py, you are trying to access the namespace subone in subtwo.py and in the namespace "subone", there should be a attribute "a". 当你在subtwo.py中执行subone.a时,你试图访问subtwo.py和命名空间“subone”中的命名空间subone,应该有一个属性“a”。

When you do - import subone in subtwo.py, then subone is added to the namespace and subone namespace has attribute a. 当你这样做 - 在subtwo.py中导入subone时,subone被添加到命名空间,subone命名空间有属性a。 so subone.a will work. 所以subone.a会起作用。

I would also suggest that you play with dir() to see how namespaces are being added. 我还建议您使用dir()来查看如何添加命名空间。

In subtwo.py, you can do the following: 在subtwo.py中,您可以执行以下操作:

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

Similarly, try adding "print dir()" before and after your import statements and the idea should become clear to you. 同样,尝试在导入语句之前和之后添加“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 “import x”将“x”添加到当前模块名称空间,而“from x import *”将所有模块级属性直接添加到当前模块名称空间

So in your above first example of main.py, subone.py and subtwo.py, the namespace in main.py will contain 'subone' and 'subtwo' while subtwo.py will have an empty namespace and can not access subone.a. 因此,在上面的main.py,subone.py和subtwo.py的第一个示例中,main.py中的命名空间将包含'subone'和'subtwo',而subtwo.py将具有空命名空间并且无法访问subone.a 。

[Edit: Some more explanations] Consider following files: main.py [编辑:更多解释]请考虑以下文件: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 subone.py

a = 'abc'

subtwo.py subtwo.py

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

And the output of running main.py: 并运行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. You will notice that importing a module subtwo.py, the print statement is executed immediately. 您会注意到导入模块subtwo.py时,会立即执行print语句。
  2. So when subone and subtwo are imported in main.py, the namespace of main.py is augmented. 因此,当在main.py中导入subone和subtwo时,main.py的命名空间会被扩充。
  3. That does not mean that namespace of subtwo will be augmented. 这并不意味着将增加subtwo的命名空间。 so "a" is available only in main.py via subone.a 所以“a”只能通过subone.a在main.py中使用
  4. When we do import subone in subtwo.py then the namespace of subtwo is augmented with subone and attribute a of module subone is available in subtow.py via subone.a 当我们在subtwo.py中导入subone时,subwo的命名空间用subone扩充,而subow.py中的模块subone属性可通过subone.a获得。

Can you explain why you feel like subone should be available to subtwo, when subone has been imported by main? 你能解释一下为什么你觉得subone应该可用于subwo,当subone被main导入时? As it is, subtwo.py can be compiled without knowing what main.py has imported. 实际上,可以在不知道main.py导入了什么的情况下编译了subtwo.py。

Also, if a second program imports subtwo.py, should subtwo's knowledge of subone depend on which of two main programs is importing subtwo? 另外,如果第二个程序导入了subtwo.py,那么subwo对subone的了解是否取决于两个主程序中哪一个导入了subwo? This would reduce reusability of subtwo. 这会降低subtwo的可重用性。

It seems like you're thinking of the compilation as a process with a defined order, accumulating state information: compile main.py, during which we compile/import subone.py, accumulating information from it, and then we compile/import subtwo.py, using the information we've already accumulated. 看起来您正在考虑将编译作为具有已定义顺序的进程,累积状态信息:编译main.py,在此期间我们编译/导入subone.py,从中累积信息,然后编译/导入subtwo。 py,使用我们已经积累的信息。

Instead, the compilation of each module is independent of others, unless dependencies are declared. 相反,除非声明依赖关系,否则每个模块的编译都独立于其他模块。 This makes it much easier to reuse and maintain code: there are fewer hidden dependencies. 这使得重用和维护代码变得更加容易:隐藏的依赖项更少。

Is it because it's bad programming to have imported modules depend on each other without going through their 'parent' module? 这是因为导入的模块相互依赖而不通过“父”模块是不好的编程?

Not as such... It's just bad programming to have module 2 depend on module 1 without saying so , ie without module 2 declaring "I depend on module 1". 不是这样......模块2依赖于模块1 而不是这样说是错误的编程,即没有模块2声明“我依赖于模块1”。

The subtwo namespace will be totally empty unless you import subone into it. 除非您将subone导入其中,否则subtwo命名空间将完全为空。

As far as programming practices, subone and subtwo can depend on each other if so desired, you just need to explicitly link them (with an import ) 就编程实践而言,如果需要, subonesubtwo可以相互依赖,你只需要明确地链接它们(带import

Regarding your second example, "main.py" knows about Nugget but "subtwo.py" doesn't. 关于你的第二个例子,“main.py”知道Nugget但“subtwo.py”却没有。

I think it would help to think of it this way. 我认为以这种方式思考会有所帮助。 Every module (file) has to work as if the only other modules that exist are the ones that it imports. 每个模块(文件)都必须像现有的其他模块一样工作。 In this case "subtwo.py" would not be able to run by itself because it hasn't imported Nugget . 在这种情况下,“subtwo.py”将无法自行运行,因为它没有导入Nugget Essentially "subtwo.py" doesn't know what "main.py" knows. 基本上“subtwo.py”不知道“main.py”知道什么。 It shouldn't, because it could be called from anywhere by anyone, and it can't rely on anyone else importing the stuff that it needs. 它不应该,因为它可以被任何人从任何地方调用,并且它不能依赖于其他任何人导入它需要的东西。

This is because the imported modules have its own separate namespaces. 这是因为导入的模块有自己独立的命名空间。 What you wrote is very much like: 你写的非常像:

def func1():
    a = 1

def func2():
    print a

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

a = 2

func2()  # Now this will print 2.

The modules have their namespaces locally, and when you use from subone import * you import the namespace ONLY to main.py namespace which cannot be accessed by subtwo . 这些模块具有其本地的命名空间,而当你使用from subone import *导入的命名空间只main.py不能被访问的命名空间subtwo

Nevertheless - what you're trying to do is very bad practice. 然而 - 你要做的是非常糟糕的做法。 Avoid using global variables and import * , just because you will get more and more confused like now. 避免使用全局变量并import * ,因为你会像现在这样越来越混淆。


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

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

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

and maybe: http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html 也许: http//sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM