web-dev-qa-db-fra.com

Comment puis-je obtenir une liste de toutes les classes du module actuel en Python?

J'ai vu beaucoup d'exemples de personnes extraire toutes les classes d'un module, généralement quelque chose comme:

# foo.py
class Foo:
    pass

# test.py
import inspect
import foo

for name, obj in inspect.getmembers(foo):
    if inspect.isclass(obj):
        print obj

Impressionnant.

Mais je ne peux pas trouver comment obtenir toutes les classes du module current .

# foo.py
import inspect

class Foo:
    pass

def print_classes():
    for name, obj in inspect.getmembers(???): # what do I do here?
        if inspect.isclass(obj):
            print obj

# test.py
import foo

foo.print_classes()

C'est probablement quelque chose de très évident, mais je n'ai rien trouvé. Quelqu'un peut m'aider?

251
mcccclean

Essaye ça:

import sys
current_module = sys.modules[__name__]

Dans votre contexte:

import sys, inspect
def print_classes():
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj):
            print(obj)

Et encore mieux:

clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass)

Parce que inspect.getmembers() prend un prédicat.

326
Nadia Alramli

Qu'en est-il de

g = globals().copy()
for name, obj in g.iteritems():

?

17
Krab

Je ne sais pas s'il existe un moyen «approprié» de le faire, mais votre extrait de code est sur la bonne voie: ajoutez simplement import foo à foo.py, faites inspect.getmembers(foo) et cela devrait fonctionner correctement.

10
int3

J'ai pu obtenir tout ce dont j'avais besoin dans dir construit plus getattr .

# Works on pretty much everything, but be mindful that 
# you get lists of strings back

print dir(myproject)
print dir(myproject.mymodule)
print dir(myproject.mymodule.myfile)
print dir(myproject.mymodule.myfile.myclass)

# But, the string names can be resolved with getattr, (as seen below)

Bien que cela ressemble à une boule de poils:

def list_supported_platforms():
    """
        List supported platforms (to match sys.platform)

        @Retirms:
            list str: platform names
    """
    return list(itertools.chain(
        *list(
            # Get the class's constant
            getattr(
                # Get the module's first class, which we wrote
                getattr(
                    # Get the module
                    getattr(platforms, item),
                    dir(
                        getattr(platforms, item)
                    )[0]
                ),
                'SYS_PLATFORMS'
            )
            # For each include in platforms/__init__.py 
            for item in dir(platforms)
            # Ignore magic, ourselves (index.py) and a base class.
            if not item.startswith('__') and item not in ['index', 'base']
        )
    ))
7
ThorSummoner
import pyclbr
print(pyclbr.readmodule(__name__).keys())

Notez que le module de navigation de classe Python de stdlib utilise une analyse de source statique, de sorte qu'il ne fonctionne que pour les modules sauvegardés par un fichier .py réel.

6
ncoghlan

Si vous voulez avoir toutes les classes qui appartiennent au module actuel, vous pouvez utiliser ceci:

import sys, inspect
def print_classes():
    is_class_member = lambda member: inspect.isclass(member) and member.__module__ == __name__
    clsmembers = inspect.getmembers(sys.modules[__name__], is_class_member)

Si vous utilisez la réponse de Nadia et que vous importez d'autres classes de votre module, ces classes seront également importées.

C'est pourquoi member.__module__ == __name__ est ajouté au prédicat utilisé sur is_class_member. Cette déclaration vérifie que la classe appartient vraiment au module.

Un prédicat est une fonction (appelable) qui renvoie une valeur booléenne.

4
Benjy Malca

C'est la ligne que j'utilise pour obtenir toutes les classes qui ont été définies dans le module actuel (c'est-à-dire non importées). Selon PEP-8, c'est un peu long, mais vous pouvez le changer à votre guise.

import sys
import inspect

classes = [name for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass) 
          if obj.__module__ is __name__]

Cela vous donne une liste des noms de classe. Si vous voulez que les objets de classe eux-mêmes conservent simplement obj à la place.

classes = [obj for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass)
          if obj.__module__ is __name__]

Cela a été plus utile dans mon expérience.

2
Austin Mackillop

Une autre solution qui fonctionne en Python 2 et 3:

#foo.py
import sys

class Foo(object):
    pass

def print_classes():
    current_module = sys.modules[__name__]
    for key in dir(current_module):
        if isinstance( getattr(current_module, key), type ):
            print(key)

# test.py
import foo
foo.print_classes()
2
Florian

Je pense que vous pouvez faire quelque chose comme ça.

class custom(object):
    __custom__ = True
class Alpha(custom):
    something = 3
def GetClasses():
    return [x for x in globals() if hasattr(globals()[str(x)], '__custom__')]
print(GetClasses())`

si vous avez besoin de cours particuliers

0
Rain0Ash