我创建了以下两个类和主函数来测试这个问题,并发现了另一个有趣的副作用。B和C类在不同的导入情况下引用ClassA。B和C完全相同,只是B在主函数中,而C被导入。
ClassX.py
class ClassA(object):
def print_a(self):
print "this is class a"
class ClassC(object):
def ref_a(self):
print 'from C ref a ==>',
xa=ClassA()
xa.print_a()
def ref_ca(self):
print 'from C ref ca ==>',
xa=ca()
xa.print_a()
test_scope.py
from classes.ClassX import ClassA
from classes.ClassX import ClassA as ca
from classes.ClassX import ClassC as cb
class ClassB(object):
def ref_a(self):
print 'from B ref a ==>',
xa=ClassA()
xa.print_a()
def ref_ca(self):
print 'from B ref ca ==>',
xa=ca()
xa.print_a()
print 'globals:',dir()
print 'modules','ca:',ca,'cb:',cb,'CA:',ClassA
print ''
print 'from main'
xb=ClassB()
xb.ref_a()
xb.ref_ca()
print ''
print 'from imports'
xbs=cb()
xbs.ref_a()
xbs.ref_ca()
结果如下:
globals: ['ClassA', 'ClassB', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'ca', 'cb']
modules ca: <class 'classes.ClassX.ClassA'> cb: <class 'classes.ClassX.ClassC'> CA: <class 'classes.ClassX.ClassA'>
from main
from B ref a ==> this is class a
from B ref ca ==> this is class a
from imports
from C ref a ==> this is class a
from C ref ca ==>
Traceback (most recent call last):
File "test_scope.py", line 32, in <module>
xbs.ref_ca()
File "R:\python\test_scripts\scope\classes\ClassX.py", line 13, in ref_ca
xa=ca()
NameError: global name 'ca' is not defined
Press any key to continue . . .
根据我的测试,我发现作为导入的对象ca对于ClassC是不可用的,但是模块ClassA是可用的(没有使用as导入)。
- 为什么导入和导入 as 的行为会有差异?我不清楚为什么主要的全局变量对于导入的类不可用。
- 动态确定适当的db_util模块进行导入并使其可访问其他已导入的类的良好方法是什么?
更新: 在阅读另一篇关于命名空间的帖子后:“Visibility of global variables from imported modules”,我明白了上面的例子中ClassC可以访问ClassA的原因是A和C在同一个导入的文件中,因此在同一个命名空间中。
因此,剩下的问题是一个设计问题:
如果我的代码像这样:
if db == 'MySQL':
from mysql_db import db_util
elif db == 'Postgres'
from postgres_db import db_util
什么是使db_util在所有导入的模块中可用的好方法?
更新:根据Blckknght的响应,我添加了代码。
cb.ca =ca
将xa=ca()的类调用更改为xa=self.ca(),这样就可以将其应用到scope_test脚本中。我认为,虽然Python允许从类外部向类添加对象,但这不是一个好的设计方法,会使调试变得非常困难。
然而,由于我认为模块和类应该是独立的或者明确声明它们的依赖关系,我将使用上面的代码示例来实现这个类。
将ClassA和ClassC分别拆分到不同的模块中,在ClassC顶部,在类定义之前进行导入。
from ClassA import ClassA
from ClassA import ClassA as ca
class ClassB(object):
在我的实际情况中,我需要将db_util模块导入到多个模块中。
ci.py #新模块,用于为适当的数据库选择类
if db == 'MySQL':
from mysql_db import db_util
elif db == 'Postgres'
from postgres_db import db_util
在每个需要db_util类的模块中。
import ci
db_util=ci.db_util #add db_util to module globals
class Module(object):
这种方法的一个问题是每个使用db_util的模块都需要导入它,但它确实让依赖关系变得明显。
我将关闭这个问题,并感谢Blckknght和Armin Rigo对我的帮助,他们的回复有助于澄清这个问题。我会很感激任何与设计相关的反馈。
cb.ca = ca
,以为这样会将ca添加到cb命名空间中。但我仍然收到“全局未定义”的错误,并且当我从ClassC打印全局变量时,它打印出全局变量:['self'] -- 没有提到ca,错误仍然存在。我错过了什么? - cswaim