如何遍历所有派生自特定基类的类声明?
我在想,当我调用 setup_all()
时,elixir\sqlalchemy 是怎么知道我在模型中声明的所有实体类的?我在一个小项目中也需要这样的功能,但我完全不知道怎么做。我试着逐步跟踪 elixir 的 setup_all()
,发现它在一个“全局”的列表(或者是字典?)中保存了所有实体类的集合,但我没能抓住这个列表是怎么填充的。有没有什么想法?
2 个回答
10
对于类的定义,这个过程更简单(不需要导入)
def find_subclasses(cls):
results = []
for sc in cls.__subclasses__():
results.append(sc)
return results
我不太确定你是想要这个,还是想要对象。如果你想要对象的话:
import gc
def find_subclasses(cls):
results = []
for sc in cls.__subclasses__():
for obj in gc.get_objects():
if isinstance(obj, sc):
results.append(obj)
return results
4
回答主要问题,不涉及SQLAlchemy或Elixir - 是的,在Python中这是可能的。
标准库中的垃圾回收器(gc
)模块有一个函数,可以让你获取到所有指向某个对象的引用,整个解释器范围内。任何继承类的__mro__
属性中总是会提到这个类。
因此,下面这个函数可以获取所有继承自某个特定类的类:
import gc
def find_subclasses(cls):
all_refs = gc.get_referrers(cls)
results = []
for obj in all_refs:
# __mro__ attributes are tuples
# and if a tuple is found here, the given class is one of its members
if (isinstance(obj, tuple) and
# check if the found tuple is the __mro__ attribute of a class
getattr(obj[0], "__mro__", None) is obj):
results.append(obj[0])
return results