Iterere over subklasser av en gitt klasse i en gitt modul

stemmer
15

I Python, gitt en modul X og Y en klasse, hvordan kan jeg iterere eller generere en liste over alle undergrupper av Y som finnes i modulen X?

Publisert på 04/09/2008 klokken 18:05
kilden bruker
På andre språk...                            


4 svar

stemmer
20

Selv Quamrana forslag fungerer fint, det er et par mulige forbedringer jeg vil gjerne foreslå å gjøre det mer Pytonske. De er avhengige av å bruke inspisere modulen fra standard bibliotek.

  1. Du kan unngå getattr anropet ved å bruke inspect.getmembers()
  2. Den prøve / fangst kan unngås ved å bruke inspect.isclass()

Med disse, kan du redusere det hele til en enkelt liste forståelse hvis du liker:

def find_subclasses(module, clazz):
    return [
        cls
            for name, cls in inspect.getmembers(module)
                if inspect.isclass(cls) and issubclass(cls, clazz)
    ]
Svarte 03/01/2009 kl. 01:56
kilden bruker

stemmer
11

Her er én måte å gjøre det på:

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
Svarte 04/09/2008 kl. 18:20
kilden bruker

stemmer
4

Kan jeg foreslå at ingen av svarene fra Chris Atlee og zacherates oppfyller kravene? Jeg tror denne endringen til zacerates Svaret er bedre:

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

Grunnen til at jeg er uenig med de gitte svarene er at den første ikke gir klasser som er en fjern underklasse av den gitte klassen, og den andre inneholder den gitte klassen.

Svarte 05/09/2008 kl. 22:54
kilden bruker

stemmer
1

Gitt modulen 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'>)]
Svarte 04/09/2008 kl. 18:29
kilden bruker

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