在Python中,给定模块X和类Y,如何迭代或生成模块X中存在的Y的所有子类的列表?
答案 0 :(得分:20)
虽然Quamrana的建议工作正常,但我想提出一些可能的改进,以使其更加pythonic。他们依赖于使用标准库中的inspect模块。
inspect.getmembers()
inspect.isclass()
有了这些,如果您愿意,可以将整个内容简化为单个列表:
def find_subclasses(module, clazz):
return [
cls
for name, cls in inspect.getmembers(module)
if inspect.isclass(cls) and issubclass(cls, clazz)
]
答案 1 :(得分:11)
这是一种方法:
import inspect
def get_subclasses(mod, cls):
"""Yield the classes in module ``mod`` that inherit from ``cls``"""
for name, obj in inspect.getmembers(mod):
if hasattr(obj, "__bases__") and cls in obj.__bases__:
yield obj
答案 2 :(得分:4)
我可以建议Chris AtLee和zacherates的答案都不符合要求吗? 我认为对zacerates回答的这种修改更好:
def find_subclasses(module, clazz):
for name in dir(module):
o = getattr(module, name)
try:
if (o != clazz) and issubclass(o, clazz):
yield name, o
except TypeError: pass
我不同意给定答案的原因是第一个不生成属于给定类的远程子类的类,第二个包含给定类。
答案 3 :(得分:1)
给出模块foo.py
class foo(object): pass
class bar(foo): pass
class baz(foo): pass
class grar(Exception): pass
def find_subclasses(module, clazz):
for name in dir(module):
o = getattr(module, name)
try:
if issubclass(o, clazz):
yield name, o
except TypeError: pass
>>> import foo
>>> list(foo.find_subclasses(foo, foo.foo))
[('bar', <class 'foo.bar'>), ('baz', <class 'foo.baz'>), ('foo', <class 'foo.foo'>)]
>>> list(foo.find_subclasses(foo, object))
[('bar', <class 'foo.bar'>), ('baz', <class 'foo.baz'>), ('foo', <class 'foo.foo'>), ('grar', <class 'foo.grar'>)]
>>> list(foo.find_subclasses(foo, Exception))
[('grar', <class 'foo.grar'>)]