我有一个在 Postgres & Mysql 上运行的应用程序。每个程序都会检查以确定数据库,然后将 postgres_db 作为 db_util 或 mysql_dt 作为 db_util 导入。当 main 中的代码引用 db_util 时一切正常,但如果导入了一个类,则未定义对 db_util 的引用。
我在 classes 和 main 中创建了以下内容来测试问题,并发现了另一个有趣的副作用。B类和C类在不同的导入情况下引用A类。B & C 是相同的,除了 B 是 main 并且 C 是进口的。
类X.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)。
- 为什么 import 和 import as 行为有区别?我不清楚为什么 mains 全局变量不适用于类 main 导入。
- 动态确定要导入的适当 db_util 模块并使其可供其他导入的类访问的好方法是什么?
更新: 在阅读了关于命名空间的另一篇文章后:“导入模块中全局变量的可见性”,我明白在上面的示例中,classA 对 ClassC 可用的原因是 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
到 scope_test 脚本。这需要将对xa=ca()的类调用更改为xa=self.ca()。我还认为,尽管 Python 允许,但从类外部向类添加对象并不是一种好的设计方法,并且会使调试成为一场噩梦。
但是,由于我认为模块和类应该是独立的或专门声明它们的依赖关系,因此我将使用上面的代码示例来实现这样的类。
将 ClassA 和 ClassC 拆分为单独的模块,并在 ClassC 的顶部,在类定义之前,执行导入
from ClassA import ClassA
from ClassA import ClassA as ca
class ClassB(object):
在我的实际情况下,我需要将 db_util 模块导入几个模块
ci.py #new 模块为适当的数据库选择类
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 的回答,他们的回答帮助我澄清了这个问题。我将不胜感激任何与设计相关的反馈。