Wie bekomme ich einen Funktionsnamen als String?

Lesezeit: 6 Minuten

Benutzer-Avatar
X10

Wie bekomme ich den Namen einer Funktion als String?

def foo():
    pass

>>> name_of(foo)
"foo"

my_function.__name__

Verwenden __name__ ist die bevorzugte Methode, da sie einheitlich angewendet wird. nicht wie func_namees funktioniert auch mit integrierten Funktionen:

>>> import time
>>> time.time.func_name
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'builtin_function_or_method' object has no attribute 'func_name'
>>> time.time.__name__ 
'time'

Auch die doppelten Unterstriche weisen den Leser darauf hin, dass es sich um ein besonderes Attribut handelt. Als Bonus haben Klassen und Module a __name__ -Attribut, sodass Sie sich nur einen speziellen Namen merken müssen.

  • Weil Sie in einigen Fällen ein Funktionsobjekt als Argument für Ihre Funktion erhalten und den Namen dieser Funktion anzeigen/speichern/manipulieren müssen. Vielleicht generieren Sie Dokumentation, Hilfetext, eine Historie von Aktionen usw. Also nein, Sie codieren den Funktionsnamen nicht immer fest.

    – mbargiel

    26. Juli 2013 um 14:17 Uhr

  • @mgargiel: Was ich sagen wollte ist: Angenommen, Sie haben eine Klasse, die 100 Methoden definiert, wobei alle Methoden nur Wrapper sind, die eine private Methode aufrufen und den Namen des Wrappers selbst übergeben. Etwas wie das: def wrapper(kwargs): super(ExtendedClass,self).call('wrapper', kwargs). Sie haben eine andere Wahl, nämlich: def wrapper(kwargs): super(ExtendedClass,self).call(sys._getframe().f_code.co_name, kwargs). Die Antwort von Albert Vonpupp sieht für mich also besser aus.

    – Richard Gomes

    30. August 2013 um 19:20 Uhr


  • @RichardGomes Eine Antwort ist geeignet, um den Namen innerhalb der Funktion selbst zu erhalten, die andere ist geeignet, um ihn aus einer Funktionsreferenz zu erhalten. Die geschriebene Frage des OP weist auf Letzteres hin.

    – Russell Borogove

    31. August 2013 um 0:44 Uhr

  • @RichardGomes Eigentlich bin ich auf diese Frage gekommen, um nach einer Lösung für dieses Problem zu suchen. Das Problem, das ich zu lösen versuche, ist, einen Decorator zu erstellen, mit dem alle meine Anrufe protokolliert werden können.

    – ali-hussain

    18. September 2013 um 19:36 Uhr

  • @RichardGomes-Funktionen sind erstklassige Objekte, an die mehr als nur ein Name gebunden sein kann. Das ist nicht unbedingt der Fall f.__name__ == 'f'.

    – Wim

    13. März 2014 um 20:13 Uhr

Benutzer-Avatar
Albert Vonpupp

Um den Namen der aktuellen Funktion oder Methode daraus abzurufen, beachten Sie Folgendes:

import inspect

this_function_name = inspect.currentframe().f_code.co_name

sys._getframe funktioniert auch statt inspect.currentframe obwohl letzteres den Zugriff auf eine private Funktion vermeidet.

Um stattdessen den Namen der aufrufenden Funktion zu erhalten, ziehen Sie in Betracht f_back wie in inspect.currentframe().f_back.f_code.co_name.


Wenn auch verwenden mypyes kann sich beschweren, dass:

error: Item „None“ von „Optional[FrameType]” hat kein Attribut “f_code”

Um den obigen Fehler zu unterdrücken, beachten Sie Folgendes:

import inspect
import types
from typing import cast

this_function_name = cast(types.FrameType, inspect.currentframe()).f_code.co_name

  • +1: Dies ist die Antwort, die ich gerne sehen würde. Andere Antworten gehen davon aus, dass der Aufrufer den Funktionsnamen bereits kennt, was im Kontext dieser Frage Unsinn ist.

    – Richard Gomes

    11. Juli 2013 um 16:43 Uhr

  • Richard: Nein, tut es nicht. SIE gehen davon aus, dass Sie anrufen Name oder func_name für Ihre Funktion direkt im selben Bereich, in dem sie definiert wurde, was sehr oft nicht der Fall ist. Denken Sie daran, dass Funktionen Objekte sind – sie können als Argumente an andere Funktionen weitergegeben, in Listen/Dikten für spätere Suchen oder Ausführung gespeichert werden usw.

    – mbargiel

    26. Juli 2013 um 14:24 Uhr

  • @paulus_almighty, das Graben in Stapelrahmen erscheint mir nicht abstrakt! Tatsächlich ist es so etwas wie das Gegenteil von abstrakt. Siehe die Ausführungsdetails Hinweis in den Dokumenten. Nicht alle Implementierungen von Python enthalten sys._getframe — es ist direkt mit den Interna von CPython verbunden.

    – Absender

    31. Januar 2016 um 14:42 Uhr

  • Dies funktioniert nur innerhalb der Funktion, aber die Frage gibt an, dass die Funktion nicht aufgerufen werden soll.

    – Benutzer2357112

    29. März 2016 um 0:02 Uhr


  • Falls Sie Ihre Funktion in etwas benutzerfreundlicheres und leichter zu merkendes umwandeln möchten, müssen Sie Frame 1 wie abrufen sys._getframe(1).f_code.co_namesodass Sie eine Funktion wie definieren können get_func_name() und erwarten, den gewünschten Namen der aufgerufenen Funktion zu erhalten.

    – m3nda

    4. Januar 2017 um 10:39 Uhr

Benutzer-Avatar
Markus Jarderot

my_function.func_name

Es gibt auch andere lustige Eigenschaften von Funktionen. Typ dir(func_name) sie aufzulisten. func_name.func_code.co_code ist die kompilierte Funktion, die als Zeichenfolge gespeichert wird.

import dis
dis.dis(my_function)

zeigt den Code in an fast menschenlesbares Format. 🙂

  • Was ist der Unterschied zwischen f.__name__ und f.funktionsname?

    – Federico A. Ramponi

    30. Oktober 2008 um 19:43 Uhr

  • Sam: Namen sind privat, __Namen speziell sind, gibt es einen konzeptionellen Unterschied.

    – Matthew Trevor

    31. Oktober 2008 um 3:15 Uhr

  • Falls jemand durch die vorangehende Antwort von Matthew verwirrt ist, hat das Kommentarsystem einige doppelte Unterstriche als Code für Fettdruck interpretiert. Mit Backtick maskiert, sollte die Nachricht lauten: __names__ sind privat, __names sind besonders.

    – gwideman

    20. Februar 2014 um 21:34 Uhr


  • Eigentlich denke ich, dass das Richtige ist _names sind privat (einfacher Unterstrich davor, nur eine Konvention), __names__ sind speziell (doppelte Unterstriche davor und danach). Ich bin mir nicht sicher, ob der doppelte Unterstrich formell oder als Konvention eine Bedeutung hat.

    – MestreLion

    23. August 2014 um 8:48 Uhr

  • func_name existiert nicht mehr in python3, also müssen Sie verwenden func.__name__ wenn Sie Kompatibilität wünschen

    – Daenith

    7. April 2017 um 15:50 Uhr

Wenn Sie auch an Klassenmethoden interessiert sind, hat Python 3.3+ dies getan __qualname__ zusätzlich zu __name__.

def my_function():
    pass

class MyClass(object):
    def method(self):
        pass

print(my_function.__name__)         # gives "my_function"
print(MyClass.method.__name__)      # gives "method"

print(my_function.__qualname__)     # gives "my_function"
print(MyClass.method.__qualname__)  # gives "MyClass.method"

Diese Funktion gibt den Funktionsnamen des Aufrufers zurück.

def func_name():
    import traceback
    return traceback.extract_stack(None, 2)[0][2]

Es ist wie die Antwort von Albert Vonpupp mit einem freundlichen Umschlag.

  • Ich hatte “” im Index [2]aber Folgendes hat funktioniert: traceback.extract_stack(None, 2)[0][-1]

    – Emmagras

    18. Oktober 2014 um 14:49 Uhr

  • für mich funktioniert das nicht, aber das funktioniert: traceback.extract_stack()[-1][2]

    – mike01010

    22. November 2014 um 3:54 Uhr

  • Dies funktioniert, wenn Sie den ersten Index auf 1 ändern, Sie sollten lernen, zu debuggen, bevor Sie kommentieren … traceback.extract_stack (None, 2)[1][2]

    – Jcc. Sanabria

    19. Dezember 2018 um 18:35 Uhr


Benutzer-Avatar
lfurini

import inspect

def foo():
   print(inspect.stack()[0][3])

wo

  • stack()[0] ist der Anrufer

  • stack()[3] ist der Stringname der Methode

  • Ich hatte “” im Index [2]aber Folgendes hat funktioniert: traceback.extract_stack(None, 2)[0][-1]

    – Emmagras

    18. Oktober 2014 um 14:49 Uhr

  • für mich funktioniert das nicht, aber das funktioniert: traceback.extract_stack()[-1][2]

    – mike01010

    22. November 2014 um 3:54 Uhr

  • Dies funktioniert, wenn Sie den ersten Index auf 1 ändern, Sie sollten lernen, zu debuggen, bevor Sie kommentieren … traceback.extract_stack (None, 2)[1][2]

    – Jcc. Sanabria

    19. Dezember 2018 um 18:35 Uhr


Benutzer-Avatar
radato

Ich verwende gerne einen Funktions-Decorator. Ich habe eine Klasse hinzugefügt, die auch mal die Funktion time. Angenommen, gLog ist ein Standard-Python-Logger:

class EnterExitLog():
    def __init__(self, funcName):
        self.funcName = funcName

    def __enter__(self):
        gLog.debug('Started: %s' % self.funcName)
        self.init_time = datetime.datetime.now()
        return self

    def __exit__(self, type, value, tb):
        gLog.debug('Finished: %s in: %s seconds' % (self.funcName, datetime.datetime.now() - self.init_time))

def func_timer_decorator(func):
    def func_wrapper(*args, **kwargs):
        with EnterExitLog(func.__name__):
            return func(*args, **kwargs)

    return func_wrapper

Jetzt müssen Sie Ihre Funktion nur noch dekorieren und voila

@func_timer_decorator
def my_func():

1145690cookie-checkWie bekomme ich einen Funktionsnamen als String?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy