2

我最近遇到了一个Python 类工厂实现,它非常适合我正在解决的问题。唯一的区别是我希望在不同的包中拥有基类和子类。

但是,当我尝试这样做时,每当我尝试加载基类时都会遇到问题。

结构:

基类.py

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..")

子类/__init__.py

__all__=['SubClass']

子类/SubClass.py

from BaseClass import BaseClass
class SubClassA(BaseClass):
    def __init__(self):
        print('Instantiating SubClassA')

当我尝试导入 BaseClass 时,出现以下错误:

       1 #导入基类

 ----> 2 从 BaseClass 导入 BaseClass
       3类SubClassA(BaseClass):
       4 def __init__(self):
       5 print('实例化子类A')

 ImportError:无法导入名称BaseClass

我还尝试使用“import BaseClass”,然后将“BaseClass.BaseClass”子类化,但这导致了不同的错误:

      1 导入基类
----> 2类SubClassA(BaseClass.BaseClass):
      3 def __init__(self):
      4 print('实例化子类A')

AttributeError:“模块”对象没有属性“BaseClass”

最后,如果我只是尝试创建子类目录没有问题。只有当我尝试导入 BaseClass 模块时才会出现问题。

有任何想法吗?

4

2 回答 2

2

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

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

防止递归,python对此感到满意。

[编辑]

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

东西.py

from BaseClass import BaseClass
from subclasses import *

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

NewClass ()
于 2011-04-16T11:55:18.950 回答
1

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

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

from .. BaseClass import BaseClass

..进入一个目录,然后查看那里(有点像文件路径)。另一种方法是将 BaseClass 直接放在 PYTHONPATH 上。

老实说,让两个不同的模块相互依赖听起来并不是一个好主意。最好让子类在 BaseClass 中注册。

编辑:

我所说的“向基类注册”的意思类似于以下内容:

# baseclass.py
subclasses = []
def register(cls):
    subclasses.append(cls)


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

baseclass.register(SubClassA)

现在 BaseClass 不需要知道所有不同的子类。它们注册使用,并且 BaseClass 能够在事先不知道它们的情况下使用它们。

于 2011-04-16T11:46:44.663 回答