Iterar sobre subclasses de uma determinada classe em um determinado módulo

votos
15

Em Python, dado um módulo X e uma classe Y, como eu pode iterar ou gerar uma lista de todas as subclasses de Y que existem no módulo X?

Publicado 04/09/2008 em 19:05
fonte usuário
Em outras línguas...                            


4 respostas

votos
20

Embora a sugestão de Quamrana funciona bem, há um par de possíveis melhorias que eu gostaria de sugerir a torná-lo mais Python. Eles contam com a utilização do módulo inspecionar a partir da biblioteca padrão.

  1. Você pode evitar a chamada getattr usando inspect.getmembers()
  2. A tentativa / captura pode ser evitado pelo uso inspect.isclass()

Com esses, você pode reduzir a coisa toda para uma lista única compreensão se você gosta:

def find_subclasses(module, clazz):
    return [
        cls
            for name, cls in inspect.getmembers(module)
                if inspect.isclass(cls) and issubclass(cls, clazz)
    ]
Respondeu 03/01/2009 em 02:56
fonte usuário

votos
11

Aqui está uma maneira de fazê-lo:

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
Respondeu 04/09/2008 em 19:20
fonte usuário

votos
4

Posso sugerir que nenhuma das respostas de Chris Atlee e zacherates cumprir os requisitos? Eu acho que essa modificação para zacerates resposta é melhor:

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

A razão de eu não concordar com as respostas dadas é que o primeiro não produz classes que são uma subclasse distante da classe dada, ea segunda inclui a classe dada.

Respondeu 05/09/2008 em 23:54
fonte usuário

votos
1

Dado o módulo 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'>)]
Respondeu 04/09/2008 em 19:29
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more