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
我认为,因为Nugget
和main
都直接加载到main
的命名空间,所以他们会使用NameError: name 'Nugget' is not defined
的命名空间并且能够引用彼此,但它会抛出一个Wrap
。这是因为subtwo
是在 main
的命名空间中从评估/检查之前被加载到{{1}}的命名空间中吗?
答案 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 :(得分: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
导入其中。
就编程实践而言,如果需要,subone
和subtwo
可以相互依赖,您只需要明确地链接它们(使用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