python - 动态导入所有子类
问题描述
我有一个带有许多派生类的抽象基类。我试图通过将所有派生类与基类放在同一个文件中来实现相同的行为,即如果我的类是Base
, DerivedA
, DerivedB
,DerivedC
在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()
我必须调用myclass.derived_c.DerivedC()
,因为我不能弄清楚如何(或者如果可能的话)使用 importlib 来实现from xyz import *
语句的等价物。
关于如何实现这一目标的任何建议?谢谢!
编辑:Python中动态模块导入的解决方案没有提供将所有模块中的类自动导入包的命名空间的方法。
解决方案
不久前我不得不做一些非常相似的事情,但就我而言,我必须动态地创建一个列表,其中包含特定包中基类的所有子类,所以如果你发现它有用:
- 创建一个包含您的类和所有子类
my_classes
的所有文件的包。Base
您应该在每个文件中只包含一个类。 __all__
适当设置__init__.py
以导入除(来自this answer.py
)之外的所有文件:__init__.py
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")]
使用 导入您的类
from my_classes import *
,因为我们的自定义__all__
将my_classes
包内的所有类添加到命名空间。但是,这还不允许我们直接访问子类。您必须在主脚本中像这样访问它们:
from my_classes import * from my_classes.base import Base subclasses = Base.__subclasses__()
现在subclasses
是一个列表,其中包含所有派生自 的类Base
。
推荐阅读
- javascript - 如何通过 Azure Cosmos DB 中的存储过程查询数据库
- c++ - 我们应该转向自我转让保护的新方式吗?
- bash - ssh 上的 DIR 循环
- google-colaboratory - Google Colab 突然变慢了
- algorithm - 给定一个带点的二维图,找到一条通过最多点的线
- javascript - 如何定义像 24:00 这样的时间并且不要更改为 00:00
- python - 根据日期合并两个数据框
- c# - 从互联网下载文件后如何处理导入资产?
- python - 带有分类 X 轴的 Matplotlib 功能区图 (fill_between)
- acumatica - 如何根据任何条件在报表参数中填充列表