Python-如何找到给定名称的类的所有子类?

发布于 2021-02-02 23:16:04

我需要一种工作方法来获取所有从Python基类继承的类。

关注者
0
被浏览
73
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    新型类(即objectPython中默认的from的子类)具有一种__subclasses__返回子类的方法:

    class Foo(object): pass
    class Bar(Foo): pass
    class Baz(Foo): pass
    class Bing(Bar): pass
    

    这是子类的名称:

    print([cls.__name__ for cls in Foo.__subclasses__()])
    # ['Bar', 'Baz']
    

    这是子类本身:

    print(Foo.__subclasses__())
    # [<class '__main__.Bar'>, <class '__main__.Baz'>]
    

    确认确实将子类Foo列为其基础:

    for cls in Foo.__subclasses__():
        print(cls.__base__)
    # <class '__main__.Foo'>
    # <class '__main__.Foo'>
    

    请注意,如果需要子类,则必须递归:

    def all_subclasses(cls):
        return set(cls.__subclasses__()).union(
            [s for c in cls.__subclasses__() for s in all_subclasses(c)])
    
    print(all_subclasses(Foo))
    # {<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>}
    

    请注意,如果尚未执行子类的类定义(例如,如果尚未导入子类的模块),则该子类尚不存在,也__subclasses__将找不到它。

    你提到“给定名称”。由于Python类是一流的对象,因此你不需要使用带有类名的字符串来代替类或类似的东西。你可以直接使用该类,也许应该。

    如果确实有一个表示类名称的字符串,并且想要查找该类的子类,则有两个步骤:找到给定名称的类,然后使用__subclasses__上述方法查找子类。

    如何从名称中查找类取决于你期望在何处找到它。如果希望与尝试查找该类的代码在同一模块中找到它,则

    cls = globals()[name]
    

    可以胜任这项工作,或者在极少数情况下你希望在当地人中找到它,

    cls = locals()[name]
    

    如果该类可以位于任何模块中,则你的名称字符串应包含完全限定的名称- ‘pkg.module.Foo’而不是just ‘Foo’。使用importlib加载类的模块,然后获取相应的属性:

    import importlib
    modname, _, clsname = name.rpartition('.')
    mod = importlib.import_module(modname)
    cls = getattr(mod, clsname)
    

    但是,找到该类后,cls.__subclasses__()将返回其子类的列表。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看