Gibt es in Python ohne Verwendung des traceback
Moduls eine Möglichkeit, den Namen einer Funktion innerhalb dieser Funktion zu bestimmen?
Angenommen, ich habe ein Modul foo mit einer Funktionsleiste. Gibt es bei der Ausführung foo.bar()
eine Möglichkeit für Bar, den Namen der Bar zu kennen? Oder noch besser, foo.bar
der Name?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
python
function
introspection
traceback
rauben
quelle
quelle
traceback
. Nicht einmal die Zeiten der Antworten und Kommentare scheinen dies zu unterstützen.Antworten:
Python hat keine Funktion, um auf die Funktion oder ihren Namen innerhalb der Funktion selbst zuzugreifen. Es wurde vorgeschlagen, aber abgelehnt. Wenn Sie nicht selbst mit dem Stack spielen möchten, sollten Sie entweder
"bar"
oderbar.__name__
je nach Kontext verwenden.Die angegebene Ablehnungserklärung lautet:
quelle
inspect.currentframe()
ist ein solcher Weg.print(inspect.currentframe().f_code.co_name)
quelle
[1][3]
den Namen des Anrufers ermitteln können.print(inspect.currentframe().f_code.co_name)
oder, um den Namen des Anrufers abzurufen :print(inspect.currentframe().f_back.f_code.co_name)
. Ich denke, es sollte schneller sein, da Sie nicht wie bisher eine Liste aller Stapelrahmen abrufeninspect.stack()
.inspect.currentframe().f_back.f_code.co_name
funktioniert nicht mit einer dekorierten Methode, wohingegeninspect.stack()[0][3]
...Es gibt verschiedene Möglichkeiten, um das gleiche Ergebnis zu erzielen:
Beachten Sie, dass die
inspect.stack
Anrufe tausendmal langsamer sind als die Alternativen:quelle
inspect.currentframe()
scheint ein guter Kompromiss zwischen Ausführungszeit und Verwendung von privaten Mitgliedern0.100 usec
oder so oder0.199 usec
so - hunderte Male schneller als Option 1 und 2, vergleichbar mit Option 4 (obwohl Antony Hatchkins Option 3 dreimal schneller als Option 4 fand).sys._getframe().f_code.co_name
overinspect.currentframe().f_code.co_name
einfach, weil ich dassys
Modul bereits importiert habe . Ist das eine vernünftige Entscheidung? (wenn man bedenkt, dass die Geschwindigkeiten ziemlich ähnlich erscheinen)Sie können den Namen, mit dem es definiert wurde, mit dem von @Andreas Jung gezeigten Ansatz erhalten , aber dies ist möglicherweise nicht der Name, mit dem die Funktion aufgerufen wurde:
Ob diese Unterscheidung für Sie wichtig ist oder nicht, kann ich nicht sagen.
quelle
.func_name
. Denken Sie daran, dass Klassennamen und Funktionsnamen in Python eine Sache sind und Variablen, die sich auf sie beziehen, eine andere.Foo2()
druckenFoo
. Zum Beispiel :Foo2 = function_dict['Foo']; Foo2()
. In diesem Fall ist Foo2 ein Funktionszeiger für möglicherweise einen Befehlszeilenparser.Ich wollte eine sehr ähnliche Sache, weil ich den Funktionsnamen in eine Protokollzeichenfolge einfügen wollte, die an mehreren Stellen in meinem Code stand. Wahrscheinlich nicht der beste Weg, dies zu tun, aber hier ist ein Weg, um den Namen der aktuellen Funktion zu erhalten.
quelle
f
Frame und denco
Code im Auge zu behalten . Ich benutze das nicht so sehr,Ich habe dieses praktische Dienstprogramm in der Nähe:
Verwendungszweck:
quelle
Ich denke, das
inspect
ist der beste Weg, dies zu tun. Zum Beispiel:quelle
Ich habe einen Wrapper gefunden, der den Funktionsnamen schreibt
Dies wird gedruckt
quelle
my_funky_name.__name__
. Sie können den func .__ name__ als neuen Parameter an die Funktion übergeben. func (* args, ** kwargs, my_name = func .__ name__). Um den Namen Ihres Dekorateurs aus Ihrer Funktion herauszuholen, würde dies meiner Meinung nach die Verwendung von inspect erfordern. Aber den Namen der Funktion zu bekommen, die meine Funktion innerhalb meiner laufenden Funktion steuert ... nun, das klingt wie der Beginn eines schönen Mems :)Dies ergibt sich tatsächlich aus den anderen Antworten auf die Frage.
Hier ist meine Einstellung:
Der wahrscheinliche Vorteil dieser Version gegenüber der Verwendung von inspect.stack () besteht darin, dass sie tausendfach schneller sein sollte [siehe Alex Melihoffs Beitrag und Zeitangaben zur Verwendung von sys._getframe () im Vergleich zur Verwendung von inspect.stack ()].
quelle
print(inspect.stack()[0].function)
scheint auch zu funktionieren (Python 3.5).quelle
Hier ist ein zukunftssicherer Ansatz.
Die Kombination der Vorschläge von @ CamHart und @ Yuval mit der akzeptierten Antwort von @ RoshOxymoron hat den Vorteil, dass Folgendes vermieden wird:
_hidden
und möglicherweise veraltete MethodenIch denke, das spielt sich gut mit zukünftigen Python-Versionen (getestet auf 2.7.3 und 3.3.2):
quelle
Prüfung:
Ausgabe:
quelle
Ich bin mir nicht sicher, warum die Leute es kompliziert machen:
quelle
In der IDE wird der Code ausgegeben
quelle
Sie können einen Dekorateur verwenden:
quelle
__name__
Attribut einer Funktion zu gelangen. Die Verwendung erfordert das Wissen über das, was Sie erhalten möchten, was mir in einfachen Fällen, in denen Funktionen nicht im laufenden Betrieb definiert sind, nicht sehr nützlich erscheint.Ich mache meinen eigenen Ansatz, um Super mit Sicherheit innerhalb eines Mehrfachvererbungsszenarios aufzurufen (ich habe den gesamten Code eingefügt).
Beispielnutzung:
Testen:
Ausgabe:
Innerhalb jeder mit @with_name dekorierten Methode haben Sie Zugriff auf self .__ fname__ als aktuellen Funktionsnamen.
quelle
Ich habe kürzlich versucht, die obigen Antworten zu verwenden, um aus dem Kontext dieser Funktion auf die Dokumentzeichenfolge einer Funktion zuzugreifen, aber da die obigen Fragen nur die Namenszeichenfolge zurückgaben, funktionierte dies nicht.
Zum Glück habe ich eine einfache Lösung gefunden. Wenn Sie wie ich auf die Funktion verweisen möchten, anstatt einfach die Zeichenfolge abzurufen, die den Namen darstellt, können Sie eval () auf die Zeichenfolge des Funktionsnamens anwenden.
quelle
Ich schlage vor, sich nicht auf Stapelelemente zu verlassen. Wenn jemand Ihren Code in verschiedenen Kontexten verwendet (z. B. Python-Interpreter), ändert sich Ihr Stapel und bricht Ihren Index ([0] [3]).
Ich schlage Ihnen so etwas vor:
quelle
Dies ist mit einem Dekorateur ziemlich einfach zu erreichen.
quelle