Czy w Pythonie, bez użycia traceback
modułu, istnieje sposób na określenie nazwy funkcji z poziomu tej funkcji?
Powiedzmy, że mam moduł foo z paskiem funkcji. Czy podczas wykonywania foo.bar()
paska można poznać jego nazwę? A może jeszcze lepiej foo.bar
?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
python
function
introspection
traceback
Obrabować
źródło
źródło
traceback
. Wydaje się, że nawet czasy odpowiedzi i komentarzy nie potwierdzają tego.Odpowiedzi:
Python nie ma funkcji dostępu do funkcji lub jej nazwy w samej funkcji. Zostało zaproponowane, ale odrzucone. Jeśli nie chcesz sam grać ze stosem, powinieneś użyć
"bar"
albo wbar.__name__
zależności od kontekstu.Podane powiadomienie o odrzuceniu to:
źródło
inspect.currentframe()
jest jednym z takich sposobów.print(inspect.currentframe().f_code.co_name)
źródło
[1][3]
aby uzyskać nazwę dzwoniącego.print(inspect.currentframe().f_code.co_name)
albo dostać nazwisko osoby dzwoniącej:print(inspect.currentframe().f_back.f_code.co_name)
. Myślę, że powinno to być szybsze, ponieważ nie pobierasz listy wszystkich ramek stosu, jak toinspect.stack()
robi.inspect.currentframe().f_back.f_code.co_name
nie działa z dekorowaną metodą,inspect.stack()[0][3]
ale ...Istnieje kilka sposobów na uzyskanie tego samego wyniku:
Pamiętaj, że
inspect.stack
połączenia są tysiące razy wolniejsze niż alternatywy:źródło
inspect.currentframe()
wydaje się być dobrym kompromisem między czasem wykonania a użyciem prywatnych członków0.100 usec
albo0.199 usec
ale tak czy inaczej - setki razy szybciej niż w przypadku opcji 1 i 2, porównywalnych z opcją 4 (chociaż Antony Hatchkins znalezionego opcja 3 trzy razy szybciej niż opcja 4).sys._getframe().f_code.co_name
poinspect.currentframe().f_code.co_name
prostu dlatego, że już zaimportowałemsys
moduł. Czy to rozsądna decyzja? (biorąc pod uwagę, że prędkości wydają się dość podobne)Nazwę, którą zdefiniowano, można uzyskać, stosując podejście pokazane przez @Andreas Jung , ale może to nie być nazwa, z którą funkcja została wywołana:
Czy to rozróżnienie jest dla ciebie ważne, czy nie, nie mogę powiedzieć.
źródło
.func_name
. Warto pamiętać, że nazwy klas i nazwy funkcji w Pythonie to jedno, a odnoszące się do nich zmienne to inna.Foo2()
wydrukowaćFoo
. Na przykład:Foo2 = function_dict['Foo']; Foo2()
. W tym przypadku Foo2 jest wskaźnikiem funkcji dla być może parsera wiersza poleceń.Chciałem bardzo podobną rzecz, ponieważ chciałem umieścić nazwę funkcji w ciągu dziennika, który poszedł w wielu miejscach w moim kodzie. Prawdopodobnie nie jest to najlepszy sposób, aby to zrobić, ale oto sposób na uzyskanie nazwy bieżącej funkcji.
źródło
f
o ramce ico
kodzie. Nie używam tego zbyt często, więc lepiej, jeśli tylkoTrzymam to przydatne narzędzie w pobliżu:
Stosowanie:
źródło
Myślę, że
inspect
to najlepszy sposób na zrobienie tego. Na przykład:źródło
Znalazłem opakowanie, które zapisze nazwę funkcji
To zostanie wydrukowane
źródło
my_funky_name.__name__
. Możesz przekazać func .__ name__ do funkcji jako nowy parametr. func (* args, ** kwargs, my_name = func .__ name__). Aby uzyskać nazwę dekoratorów z wnętrza funkcji, myślę, że wymagałoby to użycia inspekcji. Ale uzyskanie nazwy funkcji kontrolującej moją funkcję w ramach mojej działającej funkcji ... cóż, to brzmi jak początek pięknego mema :)Wynika to z innych odpowiedzi na pytanie.
Oto moje zdanie:
Prawdopodobną zaletą tej wersji w porównaniu z użyciem inspect.stack () jest to, że powinna być tysiące razy szybsza [zobacz post Alexa Melihoffa i terminy dotyczące korzystania z sys._getframe () w porównaniu z użyciem inspect.stack ()].
źródło
print(inspect.stack()[0].function)
wydaje się również działać (Python 3.5).źródło
Oto podejście przyszłościowe.
Połączenie sugestii @ CamHart i @ Yuval z zaakceptowaną odpowiedzią @ RoshOxymoron ma tę zaletę, że pozwala uniknąć:
_hidden
i potencjalnie przestarzałe metodyMyślę więc, że gra to dobrze w przyszłych wersjach Pythona (testowanych na 2.7.3 i 3.3.2):
źródło
Test:
Wynik:
źródło
Nie jestem pewien, dlaczego ludzie to komplikują:
źródło
W IDE kod wychodzi
źródło
Możesz użyć dekoratora:
źródło
__name__
atrybutu funkcji. Korzystanie wymaga znajomości rzeczy, którą próbujesz uzyskać, co nie wydaje mi się bardzo przydatne w prostych przypadkach, w których funkcje nie są definiowane w locie.Robię swoje własne podejście używane do wywoływania super z bezpieczeństwem w scenariuszu wielokrotnego dziedziczenia (umieszczam cały kod)
przykładowe użycie:
testowanie:
wynik:
Wewnątrz każdej dekorowanej metody @with_name masz dostęp do siebie .__ fname__ jako bieżąca nazwa funkcji.
źródło
Niedawno próbowałem użyć powyższych odpowiedzi, aby uzyskać dostęp do dokumentacji funkcji z kontekstu tej funkcji, ale ponieważ powyższe pytania zwracały tylko ciąg nazwy, nie działało.
Na szczęście znalazłem proste rozwiązanie. Jeśli tak jak ja, chcesz odwoływać się do funkcji zamiast po prostu uzyskać ciąg reprezentujący nazwę, którą możesz zastosować eval () do ciągu nazwy funkcji.
źródło
Sugeruję, aby nie polegać na elementach stosu. Jeśli ktoś użyje twojego kodu w różnych kontekstach (na przykład interpreter Pythona), twój stos zmieni się i zepsuje Twój indeks ([0] [3]).
Sugeruję coś takiego:
źródło
Jest to dość łatwe do osiągnięcia dzięki dekoratorowi.
źródło