从基类导入子类在Python中
我有一个基础类,这个类里面有一个方法,可以根据输入的字符串创建一个子类的实例,子类的名字和输入的字符串是一样的。
之前我把基础类和子类都放在同一个文件里,这样就可以用 globals()[name]
这种方式来实现。
不过现在我把子类分到其他文件里了。每个子类文件的顶部都有一个 import base
的语句,所以我不能直接在基础类里导入这些子类,否则就会出现循环导入的问题。
有没有什么解决办法呢?
在 base.py 文件里:
from basefactory import BaseFactory
class Base:
def __init__(self, arg1, arg2):
...
def resolve(self, element):
className = typing.getClassName(element)
return BaseFactory.getInstance(className, element, self)
在 basefactory.py 文件里:
from file1 import *
from file2 import *
...
class BaseFactory:
@staticmethod
def getInstance(name, arg1, arg2):
subclass = globals()[name]
return subclass(arg1, arg2)
在 file1.py 文件里:
from base import Base
class subclass1(Base):
def foo(self):
return self.arg1
3 个回答
我不太明白你的意思,为什么你要把子类从主类里拿出来,如果你还需要它们在里面呢?那就把它们放在主类里面,等你需要的时候,可以用 from class import subclass
来导入。
根据我的理解,你有:
- 一个基础类
- 从基础类派生出的一系列子类
- 基础类里有一个工厂方法,用来实例化正确类型的子类
- 这些子类被分成了不同的文件,并且它们依赖于基础类,但基础类里的工厂方法又依赖于这些子类
一个解决办法是创建一个单独的函数或类来实现工厂方法,并把它放在一个与基础类不同的文件中。这个文件可以导入基础类和子类的所有文件,这样就不会出现循环引用的问题。
举个例子:
# base.py:
class baseClass():
def __init__(self):
self.name = "Base"
# sub1.py:
from base import baseClass
class sub1Class(baseClass):
def __init__(self):
self.name = "sub1"
# sub2.py:
from base import baseClass
class sub2Class(baseClass):
def __init__(self):
self.name = "sub2"
# factory.py:
from sub1 import sub1Class
from sub2 import sub2Class # should not create an error
mapping = {'sub1': sub1Class, 'sub2': sub2Class}
def create(baseType):
return mapping[baseType]
其实,更好的方法可能是使用 type:
type(name, bases, dict)
会返回一个新的类型对象。这实际上是类声明的一种动态形式。name 字符串是类名,并成为 __name__
属性;bases 元组列出了基础类,并成为 __bases__
属性;而 dict
字典则是包含类体定义的命名空间,并成为 __dict__
属性。例如,以下两个语句创建的类型对象是完全相同的:
>>> class X(object):
... a = 1
...
>>> X = type('X', (object,), dict(a=1))
为什么不把 resolve 移到一个管理类里呢?可以看看 Python中的类工厂里的域类。我不确定是否需要 resolve……你可以直接通过 self.__class__.__name__
获取类名,并使用像 type()
和 isinstance()
这样的 Python 函数来检查它们是否是特定类型。
另外,看看这些链接:
你能用字符串来实例化一个类吗?
Python有没有类似于Java的Class.forName()?
你可以把出错的import
语句移动到创建子类对象的方法里面。