2016-12-17 1 views
2

Ich arbeite mit einer 3rd-Party-Bibliothek, die ich neu bin. Es gibt eine Methode, die ich anrufen möchte, aber ich kann sie nicht finden. Es ist in self ... irgendwo. Es könnte sich um ein Kindattribut oder ein Kind eines Kindes handeln, oder um ein Kind eines Kindes eines Kindes - tief in self. Aber ich kann es nicht finden. Es ist ein großer Baum, also dauert es lange, bis er gefunden ist.Wie suche ich nach einer Methode oder einem Attribut in einem Python-Objekt? (Suche alle Nachkommen)

Wie finde ich es?

Dies ist ein generisches Problem. Es kann jedem passieren, wenn er zum ersten Mal eine neue Bibliothek lernt, besonders eine komplexe. Wir alle kennen RTFM, aber manchmal ist das nicht genug. Wenn wir Zugriff auf die Quelle haben, können wir die Quelle lesen. Aber wenn die Bibliothek eine komplexe, stark dekorierte, umwickelte, umgestaltete Bibliothek des SOLID-Prinzips ist, ist das Obige möglicherweise nicht sehr fruchtbar.

Ich habe versucht, mit vars(), dir() und dem inspect Modul zu vermasseln, aber bis jetzt nicht gut. Ich benutze sie wahrscheinlich falsch.

+0

Ist die Bibliothek und ihre Quelle öffentlich verfügbar? – pvg

+0

Ja, aber das ist ein generisches Problem, dem ich beim Versuch, eine neue Bibliothek zu lernen, sehr oft begegne. – 010110110101

+0

Es gibt eine Bibliothek für [Schüler] (http://www.greenteapress.com/thinkpython/swampy/lumpy.html). Es funktioniert möglicherweise mit Ihren Objekten;) – Gribouillis

Antwort

1

Hier ist ein hackischer Code, der rekursiv durch die Attribute eines Objekts krabbelt und nach einem Attribut mit einem bestimmten Namen sucht. In diesem Beispiel wird das numpy-Paket nach einem beliebigen Attribut mit dem Namen normal durchsucht.

Bearbeiten: Der Code sucht jetzt auch in Superklassen.

import numpy 

# Hackish function doing the recursive attribute search 
def find_attr(object_name, attr_name): 
    matches = [] 
    def f(a, search, names=None, objects=None): 
     if not hasattr(a, '__dict__'): 
      return 
     if names is None: 
      names = [] 
      objects = [] 
     for varname, var in vars(a).items(): 
      if varname in names: 
       if var in objects: 
        continue 
      if varname == search: 
       matches.append(object_name + '.' + varname1 + '.' + '.'.join(names + [varname])) 
      result = f(var, search, names + [varname], objects + [var]) 
    mother_obj = eval(object_name) 
    for varname1 in dir(mother_obj): 
     if varname1 == attr_name: 
      matches.append(object_name + '.' + varname1) 
     try: 
      var = getattr(mother_obj, varname1) 
     except AttributeError: 
      continue 
     f(var, attr_name) 
    return sorted(matches, key=len) 

# Define your search 
object_name = 'numpy' 
attr_name = 'normal' 

# Do the search 
matches = find_attr(object_name, attr_name) 
print('\n'.join(matches)) 

Das gibt mir 1240 Ergebnisse, die ersten numpy.random.normal zu sein.

Beachten Sie, dass die Suche bei der Suche in einem tiefen Objekt wie dieser etwas dauern kann. Das obige Beispiel dauert 2 Minuten auf meinem Computer.

+0

Dies ist ein Anfang. Wie wäre es mit einem bereits instanziierten Objekt? – 010110110101

+0

Dies sollte für ein bereits instanziiertes Objekt funktionieren. Schreiben Sie einfach den Namen des Objekts als String in 'Objektname'. –

+0

Ich habe den Code aktualisiert. Es finden jetzt mehr Ergebnisse als zuvor, da auch Superklassen von Instanzen gesucht werden. –

Verwandte Themen