Iterieren Sie über Unterklassen einer bestimmten Klasse in einem bestimmten Modul

StackOverflow https://stackoverflow.com/questions/44352

  •  09-06-2019
  •  | 
  •  

Frage

Wie kann ich in Python bei einem gegebenen Modul X und einer Klasse Y iterieren oder eine Liste aller Unterklassen von Y generieren, die in Modul X vorhanden sind?

War es hilfreich?

Lösung

Hier ist eine Möglichkeit:

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

Andere Tipps

Obwohl Quamranas Vorschlag gut funktioniert, möchte ich einige mögliche Verbesserungen vorschlagen, um ihn pythonischer zu gestalten.Sie verlassen sich auf die Verwendung des Inspektionsmoduls aus der Standardbibliothek.

  1. Sie können den getattr-Aufruf vermeiden, indem Sie verwenden inspect.getmembers()
  2. Der Try/Catch kann durch die Verwendung vermieden werden inspect.isclass()

Mit diesen können Sie das Ganze auf Wunsch auf ein einziges Listenverständnis reduzieren:

def find_subclasses(module, clazz):
    return [
        cls
            for name, cls in inspect.getmembers(module)
                if inspect.isclass(cls) and issubclass(cls, clazz)
    ]

Kann ich vorschlagen, dass keine der Antworten von Chris AtLee und Zacherates die Anforderungen erfüllt?Ich denke, diese Änderung der Zacerates-Antwort ist besser:

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

Der Grund, warum ich mit den gegebenen Antworten nicht einverstanden bin, liegt darin, dass die erste keine Klassen erzeugt, die eine entfernte Unterklasse der gegebenen Klasse sind, und die zweite die gegebene Klasse einschließt.

Gegeben sei das Modul 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'>)]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top