新样式类(即从object,这是Python 3中的缺省值。__subclasses__方法,该方法返回以下子类:class Foo(object): passclass Bar(Foo): passclass Baz(Foo): passclass Bing(Bar): pass
以下是子类的名称:print([cls.__name__ for cls in Foo.__subclasses__()])# ['Bar', 'Baz']
下面是子类本身:print(Foo.__subclasses__())# [, ]
确认子类确实列出Foo作为他们的基础:for cls in Foo.__subclasses__():
print(cls.__base__)# #
注意,如果您想要子类,您必须递归: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))# {,
, }
注意,如果尚未执行子类的类定义(例如,如果尚未导入子类的模块),则该子类还不存在,并且__subclasses__不会找到的。
你提到了“有名无实”。因为Python类是第一类对象,所以不需要使用带有类名的字符串来代替类或类似的东西。您可以直接使用这个类,您可能应该这样做。
如果确实有一个字符串表示类的名称,并且希望找到该类的子类,那么有两个步骤:查找给定名称的类,然后用__subclasses__如上段所述。
如何从名称中找到类取决于您期望在哪里找到它。如果您希望在与试图定位类的代码相同的模块中找到它,那么cls = globals()[name]
会做这件事,或者在不太可能的情况下,你会在当地人身上找到它,cls = locals()[name]
如果类可能在任何模块中,那么您的名称字符串应该包含完全限定的名称-类似于'pkg.module.Foo'而不是仅仅'Foo'..使用importlib要加载类的模块,请检索相应的属性:import importlib
modname, _, clsname = name.rpartition('.')mod = importlib.import_module(modname)cls = getattr(mod, clsname)
不管你发现了哪一门课,cls.__subclasses__()然后返回其子类的列表。