Frage

Der folgende Code

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

Ausgänge

C
D

Wie bekomme ich es zur Ausgabe in der Reihenfolge, in der diese Klassen im Code definiert wurden? D.

D
C

Gibt es eine Möglichkeit andere als die Verwendung von inspect.getsource (A) und dem Parsen das?

War es hilfreich?

Lösung

Das inspect Modul hat auch die findsource Funktion. Es gibt ein Tupel von Versorgungsleitungen und die Zeilennummer, wo das Objekt definiert ist.

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

Die findsource Funktion Trog tatsächlich sucht die Quelldatei und sucht nach möglichen Kandidaten, wenn es ein Klasse-Objekt angegeben wird.

Bei einer Methoden-, funktions-, traceback-, Rahmen- oder Code-Objekt, es sieht einfach am co_firstlineno Attribute des (enthalten) Code-Objekts.

Andere Tipps

Beachten Sie, dass das Parsen erfolgt bereits für Sie in inspizieren - werfen Sie einen Blick auf inspect.findsource, die das Modul für die Klassendefinition sucht und gibt die Quelle und die Zeilennummer. Sortierung auf dieser Linie Nummer (Sie können auch Klassen aufzuschlüsseln müssen in separaten Modulen definiert) sollte die richtige Reihenfolge geben.

Allerdings ist diese Funktion scheint nicht dokumentiert zu werden, und ist nur einen regulären Ausdruck mit der Linie zu finden, so kann es nicht allzu zuverlässig sein.

Eine weitere Option ist metaclasses zu verwenden, oder auf eine andere Weise, entweder implizit oder explizit Informationen zum Objekt zu bestellen. Zum Beispiel:

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"))

Dies ist jedoch eine ziemlich aufdringlich Änderung (erfordert die Metaklasse aller Klassen Einstellung, die Sie in zu OrderedMeta interessiert sind)

Nein, Sie können nicht diese Attribute in der Bestellung erhalten Sie suchen. Python-Attribute werden in einer dict gespeichert (lies: hashmap), die kein Bewusstsein Einsteckrichtung Ordnung hat.

Außerdem würde ich die Verwendung von eval vermeiden, indem sie einfach zu sagen,

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

in der Schleife. Beachten Sie, dass Sie können auch iterieren nur durch Schlüssel / Wert-Paare in A.__dict__

AFAIK, nein - es ist nicht *. Dies liegt daran, alle Attribute einer Klasse werden in einem Wörterbuch gespeichert (das ist, wie Sie wissen, ungeordnete).

*: es könnte tatsächlich möglich sein, aber das würde entweder Dekorateure erfordern oder möglicherweise metaclass Hacking. Wählen Sie eine von diesen interessiert?

Ich versuche nicht, glib, hier zu sein, aber wäre es möglich, dass Sie die Klassen in Ihrer Quelle alphabetisch zu organisieren? Ich finde, dass, wenn es viele Klassen in einer Datei ist dies in seinem eigenen Recht nützlich sein kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top