【发布时间】:2008-09-04 18:05:23
【问题描述】:
在 Python 中,给定一个模块 X 和一个类 Y,我如何迭代或生成模块 X 中存在的所有 Y 子类的列表?
【问题讨论】:
在 Python 中,给定一个模块 X 和一个类 Y,我如何迭代或生成模块 X 中存在的所有 Y 子类的列表?
【问题讨论】:
尽管 Quamrana 的建议效果很好,但我还是想提出一些可能的改进建议,使其更符合 Python 风格。他们依赖于使用标准库中的检查模块。
inspect.getmembers() 避免 getattr 调用
inspect.isclass() 可以避免try/catch
有了这些,如果你愿意,你可以将整个事情简化为一个列表理解:
def find_subclasses(module, clazz):
return [
cls
for name, cls in inspect.getmembers(module)
if inspect.isclass(cls) and issubclass(cls, clazz)
]
【讨论】:
cls for name, cls in inspect.getmembers(module)
这是一种方法:
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
【讨论】:
我可以建议 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
我不同意给定答案的原因是第一个不会产生与给定类的远距离子类的类,而第二个包含给定类。
【讨论】:
给定模块 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'>)]
【讨论】: