Python Selbstbeobachtung: Wie eine ‚unsortiert‘ Liste der Objektattribute bekommen?
-
11-07-2019 - |
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?
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.