web-dev-qa-db-fra.com

Comment obtenez-vous toutes les classes définies dans un module mais non importées?

J'ai déjà vu la question suivante, mais elle ne m'a pas tout à fait où je veux: Comment puis-je obtenir une liste de toutes les classes dans le module actuel en Python?

En particulier, je ne veux pas de classes importées, par exemple si j'avais le module suivant:

from my.namespace import MyBaseClass
from somewhere.else import SomeOtherClass

class NewClass(MyBaseClass):
    pass

class AnotherClass(MyBaseClass):
    pass

class YetAnotherClass(MyBaseClass):
    pass

Si j'utilise clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass) comme le suggère la réponse acceptée dans la question liée, elle retournerait MyBaseClass et SomeOtherClass en plus des 3 définis dans ce module.

Comment puis-je obtenir uniquement NewClass, AnotherClass et YetAnotherClass?

44
Davy8

Inspectez le __module__ attribut de la classe pour savoir dans quel module il a été défini.

25

Je m'excuse d'avoir répondu à une question aussi ancienne, mais je ne me sentais pas à l'aise d'utiliser le module d'inspection pour cette solution. J'ai lu quelque part qui n'était pas sûr à utiliser en production.

Initialiser toutes les classes d'un module en objets sans nom dans une liste

Voir Antonis Christofides commente la réponse 1 .

J'ai obtenu la réponse pour tester si un objet est une classe de Comment vérifier si une variable est une classe ou non?

Voici donc ma solution sans inspection

def classesinmodule(module):
    md = module.__dict__
    return [
        md[c] for c in md if (
            isinstance(md[c], type) and md[c].__module__ == module.__name__
        )
    ]

classesinmodule(modulename)
12
piRSquared

Vous pouvez également envisager d'utiliser le module "Navigateur de classes Python" dans la bibliothèque standard: http://docs.python.org/library/pyclbr.html

Comme il n'exécute pas réellement le module en question (il effectue à la place une inspection naïve des sources), il existe certaines techniques spécifiques qu'il ne comprend pas tout à fait correctement, mais pour toutes les définitions de classe "normales", il les décrira avec précision.

8
ncoghlan

J'ai utilisé ce qui suit:

# Predicate to make sure the classes only come from the module in question
def pred(c):
    return inspect.isclass(c) and c.__module__ == pred.__module__
# fetch all members of module __name__ matching 'pred'
classes = inspect.getmembers(sys.modules[__name__], pred)

Je ne voulais pas taper le nom du module actuel dans

7
rmc
from pyclbr import readmodule

clsmembers = readmodule(__name__).items()
2
drruggeri