从另一个模块访问对象
我是一名经验很少的程序员,正在用Python 3.3制作一个游戏,作为学习练习。目前我有一个主模块和一个战斗模块。
游戏中的人物是通过“Person”这个类的实例来表示的,这些实例是在主模块中创建的。不过,战斗模块显然需要访问这些人物对象。而且,我可能还会创建更多的模块,它们也需要访问这些对象。
我该如何让其他模块访问main.py中的Person对象呢?
现在,main.py的开头有
import combat
;但是在combat.py中添加
import main
似乎没有什么帮助。
我是否应该在一个单独的模块(比如common.py)中实例化我的对象,然后在每个需要访问它们的模块中导入这些对象呢?
2 个回答
如果你在 combat
模块中通过 import main
导入了主模块,那么你需要用 main.*
来访问主模块里的类和方法。
举个例子:
import main
person = main.Person()
你也可以用 from main import *
或 import Person
来避免在前面使用 main.*
。
关于导入模块,有一些规则,详细内容可以参考这个链接:http://effbot.org/zone/import-confusion.htm:
import X
会导入模块 X,并在当前的命名空间中创建一个对这个模块的引用。换句话说,执行完这个语句后,你可以用X.name
来引用模块 X 中定义的内容。from X import *
会导入模块 X,并在当前的命名空间中创建对该模块所有公共对象的引用(也就是所有名字不以“_”开头的东西)。换句话说,执行完这个语句后,你可以直接用简单的名字来引用模块 X 中的内容。但是 X 本身并没有被定义,所以X.name
是不行的。如果名字已经被定义了,它会被新版本替换。如果 X 中的名字指向了其他对象,你的模块是不会察觉到的。from X import a, b, c
会导入模块 X,并在当前的命名空间中创建对指定对象的引用。换句话说,现在你可以在程序中使用a
、b
和c
。最后,
X = __import__(‘X’)
的效果和import X
一样,区别在于你1) 以字符串的形式传递模块名,
2) 明确地将其赋值给当前命名空间中的一个变量。
是的,你应该把这个问题分开处理。你现在的做法是模块之间的循环导入,这通常会引发更多问题,而不是解决问题。如果 combat
导入了 main
,而 main
又导入了 combat
,那么在你尝试导入时,可能会出现错误,因为 main
中的一些对象定义在那时还没有准备好。这是因为当 combat
开始执行导入时,main
还没有执行完。如果 main
是你的启动脚本,它应该只做一件事,就是通过调用另一个模块的方法来启动程序;如果所需的方法是某个类的实例方法,它也可以创建一个对象。尽量避免使用全局变量。即使现在看起来没问题,将来也可能会带来麻烦。
话说回来,你可以这样引用模块中的成员:
import common
x = common.some_method_in_common()
y = common.SomeClass()
或者
from common import SomeClass
y = SomeClass()
就我个人而言,我一般不直接引用另一个模块的方法,而是加上模块名,但这样做也是可以的:
from common import some_method_in_common
x = some_method_in_common()
我通常对类使用 from ... import ...
的方式,而对方法则通常使用第一种形式。(是的,这有时意味着我会从一个模块中单独导入特定的类,除了导入整个模块。)但这只是我个人的习惯。
还有一种语法是 强烈 不推荐 的:
from common import *
y = SomeClass()
这种方式会把 common
中所有不以下划线(_
)开头的成员导入到当前的作用域中。之所以不推荐,是因为这样会让你很难辨别名字的来源,而且容易导致错误。想想这对导入:
from common import *
from some_other_module import *
y = SomeClass()
那么 SomeClass
是来自哪个模块的呢?除了去查看这两个模块,根本无法判断。更糟糕的是,如果两个模块都定义了 SomeClass
,或者 SomeClass
后来被添加到 some_other_module
中,那就更麻烦了。