Python类工厂问题引用基类?

Python class factory problem referencing base class?

我最近遇到了一个Python类工厂实现,它非常适合我正在处理的一个问题。唯一的区别是我想要在不同的包中有基础类和子类。

然而,当我尝试这样做时,每当我试图加载基类时,都会遇到一个问题。

结构:

BaseCalas.Py

1
2
3
4
5
6
7
8
9
10
from subclasses import *

def NewClass():
   """Map Factory"""
    for cls in BaseClass.__subclasses__():
        print"checking class..."

class BaseClass(object):
    def __init__(self):
        print("Building an abstract BaseMap class..")

子类/uu init_uuu.py

1
__all__=['SubClass']

子类/子类.py

1
2
3
4
from BaseClass import BaseClass
class SubClassA(BaseClass):
    def __init__(self):
        print('Instantiating SubClassA')

当我尝试导入基类时,我得到以下错误:

1
2
3
4
5
6
7
8
       1 #import BaseClass

 ----> 2 from BaseClass import BaseClass
       3 class SubClassA(BaseClass):
       4     def __init__(self):
       5         print('Instantiating SubClassA')

 ImportError: cannot import name BaseClass

我还尝试使用"import baseclass",然后对"baseclass.baseclass"进行子类化,但这导致了另一个错误:

1
2
3
4
5
6
      1 import BaseClass
----> 2 class SubClassA(BaseClass.BaseClass):
      3     def __init__(self):
      4         print('Instantiating SubClassA')

AttributeError: 'module' object has no attribute 'BaseClass'

最后,如果我只是尝试创建子类目录,就没有问题了。只有当我尝试导入基类模块时,事情才会出错。

有什么主意吗?


一些实验表明问题在于导入递归。使baseclass.py中的import语句有条件地解决了我的测试的问题:

1
2
if __name__ == '__main__':
    from subclasses import *

防止递归,而python似乎对此很满意。

[编辑]

更好的解决方案是将newClass方法放在单独的文件中:

某物

1
2
3
4
5
6
7
8
9
from BaseClass import BaseClass
from subclasses import *

def NewClass():
   """Map Factory"""
    for cls in BaseClass.__subclasses__():
        print ("checking class...")

NewClass ()


如果没有更多的信息,您的模块BaseClass似乎不直接在python路径上。基类能够找到子类,因为它们存在于直接位于基类下面的目录中。反之亦然。

相对导入可以解决此问题。

1
from .. BaseClass import BaseClass

..将进入一个目录,并查看那里(类似于文件路径)。另一种方法是将baseclass直接放在pythonpath上。

有两个不同的模块相互依赖听起来不是一个好主意,尽管说实话。最好用基类注册子类。

编辑:

我所说的"注册基类"是指如下所示:

1
2
3
4
5
6
7
8
9
10
11
# baseclass.py
subclasses = []
def register(cls):
    subclasses.append(cls)


# subclass.py
class SubClassA(BaseClass):
    ...

baseclass.register(SubClassA)

现在,基类不需要知道所有不同的子类。它们注册后就可以使用了,而baseclass可以在不知道它们的情况下使用它们。