如何遍历所有派生自特定基类的类声明?

4 投票
2 回答
826 浏览
提问于 2025-04-17 10:48

我在想,当我调用 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

撰写回答