Question

Le code suivant

import types
class A:
    class D:
        pass
    class C:
        pass
for d in dir(A):
    if type(eval('A.'+d)) is types.ClassType:
        print d

sorties

C
D

Comment puis-je le faire sortir dans l'ordre dans lequel ces classes ont été définies dans le code? I.e.

D
C

Existe-t-il un autre moyen que d'utiliser inspect.getsource (A) et de l'analyser?

Était-ce utile?

La solution

Le module inspect possède également la fonction findource . Il retourne un tuple de lignes source et un numéro de ligne où l'objet est défini.

>>> import inspect
>>> import StringIO
>>> inspect.findsource(StringIO.StringIO)[1]
41
>>>

La fonction findource effectue une recherche dans le fichier source et recherche les candidats probables si un objet de classe lui est attribué.

Étant donné un objet méthode, fonction, traceback, cadre ou code, il se contente de regarder l'attribut co_firstlineno de l'objet code (contenu).

Autres conseils

Notez que cette analyse est déjà effectuée pour vous dans inspect - jetez un coup d'œil à inspect.findsource , qui recherche dans le module la définition de la classe et renvoie le numéro de source et le numéro de ligne. Le tri sur ce numéro de ligne (vous devrez peut-être également séparer les classes définies dans des modules distincts) doit donner le bon ordre.

Cependant, cette fonction ne semble pas être documentée et utilise simplement une expression régulière pour rechercher la ligne. Elle n'est donc peut-être pas très fiable.

Une autre option consiste à utiliser des métaclasses, ou un autre moyen de classer des informations de manière implicite ou explicite dans l'objet. Par exemple:

import itertools, operator

next_id = itertools.count().next

class OrderedMeta(type):
    def __init__(cls, name, bases, dct):
        super(OrderedMeta, cls).__init__(name, bases, dct)
        cls._order = next_id()

# Set the default metaclass
__metaclass__ = OrderedMeta

class A:
    class D:
        pass
    class C:
        pass

print sorted([cls for cls in [getattr(A, name) for name in dir(A)] 
           if isinstance(cls, OrderedMeta)], key=operator.attrgetter("_order"))

Cependant, il s’agit d’un changement assez intrusif (vous devez définir la métaclasse de toutes les classes qui vous intéressent sur OrderedMeta)

Non, vous ne pouvez pas obtenir ces attributs dans l'ordre que vous recherchez. Les attributs Python sont stockés dans un dict (read: hashmap), qui n'a aucune conscience de l'ordre d'insertion.

De même, j'éviterais d'utiliser eval en disant simplement

if type(getattr(A, d)) is types.ClassType:
    print d

dans votre boucle. Notez que vous pouvez également parcourir les paires clé / valeur dans A .__ dict __

Autant que je sache, non - il n'y a pas *. En effet, tous les attributs d’une classe sont stockés dans un dictionnaire (non ordonné, comme vous le savez).

*: cela pourrait effectivement être possible, mais cela nécessiterait soit des décorateurs, soit éventuellement du piratage métaclasse. Est-ce que l'un ou l'autre de ces centres vous intéresse?

Je n'essaie pas d'être désinvolte ici, mais serait-il possible pour vous d'organiser les cours dans votre source par ordre alphabétique? Je trouve que quand il y a beaucoup de classes dans un fichier, cela peut être utile en soi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top