Wie erhalte ich eine vollständige Liste der Methoden und Attribute des Objekts?

230
dir(re.compile(pattern)) 

gibt kein Muster als eines der Elemente der Liste zurück. Es gibt nämlich zurück:

['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']

Laut Handbuch soll es enthalten

die Namen der Attribute des Objekts, die Namen der Attribute seiner Klasse und rekursiv die Attribute der Basisklassen seiner Klasse.

Es sagt auch das

Die Liste ist nicht unbedingt vollständig.

Gibt es einen Weg, um die zu bekommen vollständige Liste zu erhalten? Ich habe immer angenommen, dass dir eine vollständige Liste zurückgibt, aber anscheinend nicht ...

Außerdem: Gibt es eine Möglichkeit, nur Attribute aufzulisten? Oder nur Methoden?

Bearbeiten: Dies ist eigentlich ein Fehler in Python -> angeblich ist es im 3.0-Zweig behoben (und vielleicht auch in 2.6)

Bartosz Radaczyński
quelle
5
Die Verwendung dir()oder das Inspect-Modul ist im Allgemeinen der richtige Weg, dies zu tun. Haben Sie das reModul nur als Beispiel verwendet oder möchten Sie ein spezielles Ziel erreichen?
1
Sind Sie sicher, dass das Muster nach dem Kompilieren tatsächlich als Daten beibehalten wird? Ich hatte den Eindruck, dass der Sinn des Kompilierens eines Musters darin bestand, die endlichen Zustandsautomaten zu erzeugen, die zum Parsen des gegebenen Musters erforderlich sind.
Kyle Strand
@hop kann nicht von Klassen umgangen werden? Zum Beispiel können sie ihre auf machen__dir__()
ytpillai
ytpillai: richtig, aber nur in Python 3. Trotzdem ist die Frage, ob eine solche Klasse unter den "allgemeinen Fall" fallen würde

Antworten:

140

Für die vollständige Liste der Attribute lautet die kurze Antwort: Nein. Das Problem ist, dass die Attribute tatsächlich als die Argumente definiert sind, die von der getattrintegrierten Funktion akzeptiert werden . Da der Benutzer erneut implementieren kann __getattr__und plötzlich jede Art von Attribut zulässt, gibt es keine generische Möglichkeit, diese Liste zu generieren. Die dirFunktion gibt die Schlüssel im __dict__Attribut zurück, dh alle Attribute, auf die zugegriffen werden kann, wenn die __getattr__Methode nicht erneut implementiert wird.

Für die zweite Frage macht es nicht wirklich Sinn. Eigentlich sind Methoden aufrufbare Attribute, nichts weiter. Sie können jedoch aufrufbare Attribute filtern und mithilfe des inspectModuls die Klassenmethoden, -methoden oder -funktionen bestimmen.

PierreBdR
quelle
1
inpect.getmembers (re.compile (pattern)) liefert auch kein Muster als Mitglied, daher wird es wahrscheinlich intern verwendet ... Das ist scheiße!
Bartosz Radaczyński
Ich könnte auch callable verwenden, um zu überprüfen, ob es sich um Methoden handelt, aber das ist nicht der Punkt ... Der Punkt ist, dass ich dir nicht vertrauen kann, auch nur die Liste der Attribute zurückzugeben, die tatsächlich öffentlich sichtbar sind ...
Bartosz Radaczyński
2
inspect soll "mindestens so" vertrauenswürdig sein wie dir (). Auf der anderen Seite ist re ein sehr kompliziertes Modul
Was definieren Sie unter "öffentlich sichtbar"? Wenn Sie meinen, dass auf "zugegriffen werden kann", ist dies aus dem angegebenen Grund eine verlorene Ursache. Andernfalls gibt 'dir' immer die Liste der Attribute zurück, auf die mit der Standardimplementierung von getattr zugegriffen werden kann.
PierreBdR
2
dir (my_class) gibt etwas anderes zurück als my_class .__ dict __. keys (). Ersteres gibt auch die Methoden der Klasse wie init und doc aus
JuanPi
58

Aus diesem Grund wurde die neue __dir__()Methode in Python 2.6 hinzugefügt

sehen:

Moe
quelle
Ich erhalte folgende Fehlermeldung: >> dir __ (pyrenderdoc) Traceback (letzter Aufruf zuletzt): Datei "<string>", Zeile 1, in <module> NameError: Name '__dir ' ist nicht definiert
Mona Jalal
__dir__ () ist eine Methode auf Objekt, keine Funktion - bitte lesen Sie die Links in der Antwort und dies
Moe
Einzeiler zum Drucken aller Attribute und ihrer Werte:pprint({k:getattr(ojb,k) for k in obj.__dir__()})
Czechnology
21

Hier ist eine praktische Ergänzung zu den Antworten von PierreBdR und Moe:

  • Für Python> = 2.6 und neuen Stil Klassen , dir()scheint genug zu sein.
  • Für Klassen im alten Stil können wir zumindest das tun, was ein Standardmodul tut, um die Tab-Vervollständigung zu unterstützen: zusätzlich zu dir(), suchen Sie nach __class__und wählen Sie dann Folgendes __bases__:

    # code borrowed from the rlcompleter module
    # tested under Python 2.6 ( sys.version = '2.6.5 (r265:79063, Apr 16 2010, 13:09:56) \n[GCC 4.4.3]' )
    
    # or: from rlcompleter import get_class_members
    def get_class_members(klass):
        ret = dir(klass)
        if hasattr(klass,'__bases__'):
            for base in klass.__bases__:
                ret = ret + get_class_members(base)
        return ret
    
    
    def uniq( seq ): 
        """ the 'set()' way ( use dict when there's no set ) """
        return list(set(seq))
    
    
    def get_object_attrs( obj ):
        # code borrowed from the rlcompleter module ( see the code for Completer::attr_matches() )
        ret = dir( obj )
        ## if "__builtins__" in ret:
        ##    ret.remove("__builtins__")
    
        if hasattr( obj, '__class__'):
            ret.append('__class__')
            ret.extend( get_class_members(obj.__class__) )
    
            ret = uniq( ret )
    
        return ret

(Testcode und Ausgabe werden der Kürze halber gelöscht, aber im Grunde genommen scheinen wir für Objekte neuen Stils dieselben Ergebnisse zu haben get_object_attrs()wie für dir(), und für Klassen alten Stils dir()scheint die Hauptaddition zur Ausgabe das __class__Attribut zu sein.)

ジ ョ ー ジ
quelle
9

Nur zur Ergänzung:

  1. dir()ist die am meisten mächtig / grundlegende Instrument. ( Am meisten empfohlen )
  2. Andere Lösungen als dir()nur die Möglichkeit , die Ausgabe von zu verarbeitendir() .

    Wenn Sie Attribute der 2. Ebene auflisten oder nicht, ist es wichtig, das Sieben selbst durchzuführen, da Sie manchmal interne Variablen mit führenden Unterstrichen heraussieben möchten __, aber manchmal benötigen Sie möglicherweise die __doc__Dokumentzeichenfolge.

  3. __dir__()und dir()gibt identischen Inhalt zurück.
  4. __dict__und dir()sind anders. __dict__gibt unvollständigen Inhalt zurück.
  5. WICHTIG : __dir__()Kann manchmal vom Autor für einen beliebigen Zweck mit einer Funktion, einem Wert oder einem Typ überschrieben werden.

    Hier ist ein Beispiel:

    \\...\\torchfun.py in traverse(self, mod, search_attributes)
    445             if prefix in traversed_mod_names:
    446                 continue
    447             names = dir(m)
    448             for name in names:
    449                 obj = getattr(m,name)

    TypeError: Der Deskriptor __dir__des 'object'Objekts benötigt ein Argument

    Der Autor von PyTorch hat die __dir__()Methode so geändert , dass ein Argument erforderlich ist. Diese Änderung schlägt dir()fehl.

  6. Wenn Sie möchten, dass ein zuverlässiges Schema alle Attribute eines Objekts durchläuft, denken Sie daran, dass jeder Python-Standard überschrieben werden kann und möglicherweise nicht gilt und jede Konvention möglicherweise unzuverlässig ist.

Chiron
quelle
5

So mache ich das, nützlich für einfache benutzerdefinierte Objekte, denen Sie ständig Attribute hinzufügen:

Gegeben ein Objekt, das mit obj = type("Obj",(object,),{})oder einfach erstellt wurde:

class Obj: pass
obj = Obj()

Fügen Sie einige Attribute hinzu:

obj.name = 'gary'
obj.age = 32

So erhalten Sie ein Wörterbuch mit nur den benutzerdefinierten Attributen:

{key: value for key, value in obj.__dict__.items() if not key.startswith("__")}

# {'name': 'gary', 'age': 32}
mluc
quelle
Liste aller Attribute in Python 3.x: {Schlüssel: Wert für Schlüssel, Wert in obj .__ dict __. items (), wenn nicht key.startswith ("__")} ['_ deklarierte_Felder']. keys ()
über_c_level