我有一个在Postgres&Mysql上运行的应用程序。每个程序检查以确定数据库,然后将postgres_db作为db_util或mysql_dt作为db_util导入。当main中的代码引用db_util时,所有这些都可以正常工作,但如果导入了类,则不会定义对db_util的引用。
我创建了下面的类和main来测试这个问题,并发现了另一个有趣的副作用。B&C类参考不同进口情况下的A类。B&C是相同的,只是B在主控和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()
测试范围.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(imported as)对ClassC不可用,但是模块ClassA可用(不带as导入)。
更新: 在阅读了另一篇关于名称空间的文章:“Visibility of global variables from imported modules”之后,我理解在上面的示例中,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
作用域测试脚本。这要求将对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#为适当的数据库选择类的新模块
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来导入它,但它确实会使依赖关系为人所知。
我将结束这一问题,并要感谢布莱克克特和阿米恩里戈他们的回答,帮助我澄清这个问题。我会感谢任何与设计相关的反馈。
你用错误的观点来处理这个问题。每个模块都是一个名称空间,以空开头,并为其运行的每个语句(通常)填充一个名称:
在ClassX.py中,我们看到名称
ca
没有在这个模块中定义,但是ClassA
和ClassC
是。因此,执行ClassX.py中的xa=ca()
行失败。一般来说,其思想是每个模块都导入它所需要的内容。您也可以从外部将名称“插入”模块,但这通常被认为是非常糟糕的样式(为非常特殊的情况保留)。
在Python中,每个模块都有自己的全局命名空间。进行导入时,只需将导入的模块添加到当前模块的命名空间中,而不是添加到任何其他模块的命名空间中。如果要将它放在另一个名称空间中,需要显式地告诉Python这一点。
主.py:
其他模块:
注意,通常不能将主模块(作为脚本执行)用作共享命名空间。这是因为Python使用模块的
__name__
属性来确定如何缓存该模块(以便始终从多个导入中获取相同的对象),但脚本总是被赋予__name__
的"__main__"
而不是其真实名称。如果另一个模块导入main
,它们将得到一个单独(重复)的副本!相关问题 更多 >
编程相关推荐