迭代给定模块中给定类的子类

时间:2008-09-04 18:05:23

标签: python oop

在Python中,给定模块X和类Y,如何迭代或生成模块X中存在的Y的所有子类的列表?

4 个答案:

答案 0 :(得分:20)

虽然Quamrana的建议工作正常,但我想提出一些可能的改进,以使其更加pythonic。他们依赖于使用标准库中的inspect模块。

  1. 您可以使用inspect.getmembers()
  2. 来避免getattr调用
  3. 使用inspect.isclass()
  4. 可以避免try / catch

    有了这些,如果您愿意,可以将整个内容简化为单个列表:

    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'>)]