Python:如何查找所有继承该类的类?

55 投票
4 回答
57600 浏览
提问于 2025-04-16 16:58

有没有办法在Python中查询一个命名空间,找出所有继承自某个特定类的类?比如说,我有一个叫widget的类,我想能调用类似inheritors(widget)这样的函数,来获取我所有不同种类的widget的列表。

4 个回答

1
# return list of tuples (objclass, name) containing all subclasses in callers' module
def FindAllSubclasses(classType):
    import sys, inspect
    subclasses = []
    callers_module = sys._getframe(1).f_globals['__name__']
    classes = inspect.getmembers(sys.modules[callers_module], inspect.isclass)
    for name, obj in classes:
        if (obj is not classType) and (classType in inspect.getmro(obj)):
            subclasses.append((obj, name))
    return subclasses

当然可以!请把你想要翻译的内容发给我,我会帮你把它变得简单易懂。

23

你可以通过自己定义的元类来追踪继承关系。

import collections

class A(object):
    class __metaclass__(type):
        __inheritors__ = defaultdict(list)

        def __new__(meta, name, bases, dct):
            klass = type.__new__(meta, name, bases, dct)
            for base in klass.mro()[1:-1]:
                meta.__inheritors__[base].append(klass)
            return klass

class B(A):
    pass

class C(B):
    pass

>>> A.__inheritors__
defaultdict(<type 'list'>, {<class '__main__.A'>: [<class '__main__.B'>, <class '__main__.C'>], <class '__main__.B'>: [<class '__main__.C'>]})

任何从 A 或它的派生类继承的东西都会被记录下来。当你应用中的所有模块都加载完毕后,你将得到完整的继承关系图。

83

你想用 Widget.__subclasses__() 来获取所有子类的列表。不过这个方法只会查找直接的子类,所以如果你想要获取所有的子类,你就需要做一些额外的工作:

def inheritors(klass):
    subclasses = set()
    work = [klass]
    while work:
        parent = work.pop()
        for child in parent.__subclasses__():
            if child not in subclasses:
                subclasses.add(child)
                work.append(child)
    return subclasses

注意:如果你使用的是 Python 2.x,这个方法只适用于新式类。

撰写回答