类B和C都派生自基类A,并且都不会覆盖A的方法test()。 B与A在同一模块中定义; C在单独的模块中定义。如何调用B.test()打印“hello”,但调用C.test()会失败?不应该调用最终执行A.test(),因此能够在mod1的命名空间中解析符号“message”吗?
我也很感激地收到关于这种行为记录在哪里的提示,因为我无法发现任何事情。调用C.test()时如何解析名称,并且可以以某种方式将“message”注入其中一个名称空间?
FWIW,我没有使用实例变量的原因(例如,设置A.message =“hello”)是因为我想要访问“全局”单例对象并且不希望有一个明确的指示对象在其他所有物体中都是如此。
mod1.py:
import mod2
class A(object):
def test(self):
print message
class B(A):
pass
if __name__ == "__main__":
message = "hello"
A().test()
B().test()
mod2.C().test()
mod2.py:
import mod1
class C(mod1.A):
pass
输出是:
$ python mod1.py
hello
hello
Traceback (most recent call last):
File "mod1.py", line 14, in <module>
mod2.C().test()
File "mod1.py", line 5, in test
print message
NameError: global name 'message' is not defined
非常感谢!
答案 0 :(得分:2)
EOL是正确的,将程序的“主要”部分移动到新文件mod3.py确实可以使事情有效。
http://bytebaker.com/2008/07/30/python-namespaces/进一步澄清了这个问题。
在我原来的问题中,事实证明变量message
存储在__main__
模块命名空间中,因为mod1.py是作为脚本运行的。 mod2导入mod1,但它获得了一个单独的mod1
命名空间,其中变量message
不存在。下面的代码片段在将message
写入mod1
的命名空间时表现得更清楚(不是我建议在现实生活中这样做),从而导致预期的行为。
import sys
class A(object):
def test(self):
print message
class B(A):
pass
if __name__ == "__main__":
import mod2
message = "hello"
sys.modules["mod1"].message = message
A().test()
B().test()
mod2.C().test()
我认为最好的现实解决办法是将程序的“主要”部分移动到一个单独的模块中,如EOL暗示的那样,或者:
class A(object):
def test(self):
print message
class B(A):
pass
def main():
global message
message = "hello"
A().test()
B().test()
# resolve circular import by importing in local scope
import mod2
mod2.C().test()
if __name__ == "__main__":
# break into mod1 namespace from __main__ namespace
import mod1
mod1.main()
答案 1 :(得分:1)
您可以使用类属性而不是全局吗?以下作品
import mod2
class A(object):
message = "Hello" # Class attribute (not duplicated in instances)
def test(self):
print self.message # Class A attribute can be overridden by subclasses
class B(A):
pass
if __name__ == "__main__":
A().test()
B().test()
mod2.C().test()
不使用全局变量更清晰:在上面的代码中,message
显式附加到它所使用的类中。
尽管如此,我也非常好奇为什么message
找不到全球mod2.C().test()
。
事情按预期工作,如果删除了交叉导入(mod1.py
中没有主程序,没有import mod2
):导入mod1
和来自mod2
的{{1}},mod3.py
那里和mod1.message = "Hello"
有效。因此,我想知道问题是否与交叉导入无关......