让我们考虑如下的包结构:
myApp
|-- myPackage
| |-- __init__.py
| +-- myModule.py
|-- __init__.py
+-- main.py
myModule.py 包含一个类,例如:
class MyClass( object ):
_myList = []
@classmethod
def test( cls ):
cls._myList.append( len( cls._myList ) )
return cls._myList
def __init__( self ):
return
pass
如您所见,没有什么花哨的,我只是将列表定义为静态类变量。现在让我们考虑 main.py 中的代码:
from myApp.myPackage.myModule import MyClass as MyClassAbs
from myPackage.myModule import MyClass as MyClassRel
if __name__ == '__main__':
print '\n myList'
print 'MyClassAbs().test():', MyClassAbs().test() #< Prints [0].
print 'MyClassRel().test():', MyClassRel().test() #< Prints [0] but should be [0, 1].
print 'MyClassAbs.test():', MyClassAbs.test() #< Prints [0, 1] but should be [0, 1, 2].
print 'MyClassRel.test():', MyClassRel.test() #< Prints [0, 1] but should be [0, 1, 2, 3].
print '\n myList ids'
print id( MyClassAbs().test() )
print id( MyClassRel().test() )
print id( MyClassAbs.test() )
print id( MyClassRel.test() )
print ''
print 'MyClassAbs == MyClassRel:', MyClassAbs == MyClassRel #< Prints False
print 'isinstance( MyClassAbs(), MyClassRel ):', isinstance( MyClassAbs(), MyClassRel ) #< Prints False
print 'isinstance( MyClassRel(), MyClassAbs ):', isinstance( MyClassRel(), MyClassAbs ) #< Prints False
pass
问题是,在我的代码中,我从同一个模块导入了两次相同的类,但方式不同:一次是绝对导入,一次是相对导入。如代码的最后一部分所示,即使类相同,它们也不相等,因为它们的模块被独特地注册到 sys.modules 中:
'myApp.myPackage.myModule': <module 'myApp.myPackage.myModule' from '/full/path/myApp/myPackage/myModule.py'>
'myPackage.myModule': <module 'myPackage.myModule' from '/full/path/myApp/myPackage/myModule.py'>
因此,它们的表示不同:
'MyClassAbs': <class 'myApp.myPackage.myModule.MyClass'>
'MyClassRel': <class 'myPackage.myModule.MyClass'>
那么......有没有办法将此变量设置为静态的好?
编辑:
上面的代码显然只是减少了我真正的问题。实际上,我基本上有一段代码,它检查递归嵌套在文件夹中的所有模块,并注册其中包含的类。以这种方式注册的所有类都可以使用通用语法进行实例化,例如
myApp.create( 'myClass' )
这就是为什么我有时最终有 2 个对象指向同一个类,但它们以不同的方式导入。一个已通过 imp.load_module() 调用自动导入,另一个将由用户通过常规导入语句直接导入。如果用户决定手动导入一个类,他应该仍然可以访问相同的静态类变量,而不是在同一个但自动注册的类中定义的变量。希望它有意义吗?