动态导入所有子类

2024-10-03 21:33:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个抽象基类和一些派生类。我试图实现与基类相同的行为,即如果我的类是BaseDerivedADerivedBDerivedC在文件myclass.py中,我可以在另一个文件中写入

import myclass
a = myclass.DerivedA()
b = myclass.DerivedB()
c = myclass.DerivedC()

但是每个派生类都在自己的文件中。这必须是动态的,也就是说,我可以删除derived_c.py并且所有的东西都能正常工作,除了现在我不能再调用myclass.DerivedC,或者如果我添加一个derived_d.py,我可以不用接触__init__.py,所以简单地使用from derived_c import DerivedC不是一个选项。在

我试着把它们都放在一个子目录中,然后放在这个目录的__init__.py中,使用pkgutil.walk_packages()动态导入所有文件,但是我不能让它们直接位于模块的命名空间中,也就是说,我必须调用myclass.DerivedC(),因为我无法确定如何(或者是否可能)使用importlib来实现等效一个from xyz import *语句的。在

有什么建议可以让我做到这一点?谢谢!在

Edit:Dynamic module import in Python的解决方案没有提供一种方法来自动将所有模块中的类导入到包的命名空间中。在


Tags: 模块文件frompyimportinitmyclass动态
1条回答
网友
1楼 · 发布于 2024-10-03 21:33:26

我曾经做过类似的事情,但在我的例子中,我必须动态地创建一个列表,其中包含一个特定包中基类的所有子类,所以万一您发现它很有用:

  1. 创建一个my_classes包,其中包含Base类和所有子类的所有文件。每个文件中只应包含一个类。在
  2. __init__.py中适当地设置__all__,导入除__init__.py(来自this answer)之外的所有{}文件:

    from os import listdir
    from os.path import dirname, basename
    
    __all__ = [basename(f)[:-3] for f in listdir(dirname(__file__)) if f[-3:] == ".py" and not f.endswith("__init__.py")]
    
  3. 使用from my_classes import *导入您的类,因为我们的自定义__all__会将my_classes包中的所有类添加到命名空间中。

  4. 但是,这还不允许我们直接访问子类。您必须在主脚本中这样访问它们:

    from my_classes import *
    from my_classes.base import Base
    
    subclasses = Base.__subclasses__()
    

现在,subclasses是一个包含从Base派生的所有类的列表。在

相关问题 更多 >