En Python, sin usar el traceback
módulo, ¿hay alguna forma de determinar el nombre de una función desde esa función?
Digamos que tengo un módulo foo con una barra de funciones. Al ejecutar foo.bar()
, ¿hay alguna forma para que el bar sepa el nombre del bar? O mejor aún, foo.bar
¿cómo se llama?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
traceback
. Ni siquiera los tiempos de respuestas y comentarios parecen respaldarlo.Respuestas:
Python no tiene una función para acceder a la función o su nombre dentro de la función misma. Se ha propuesto pero rechazado. Si no quieres jugar con la pila tú mismo, deberías usar
"bar"
obar.__name__
dependiendo del contexto.El aviso de rechazo dado es:
fuente
inspect.currentframe()
Es una de esas formas.print(inspect.currentframe().f_code.co_name)
fuente
[1][3]
para obtener el nombre de la persona que llama.print(inspect.currentframe().f_code.co_name)
o para obtener el nombre de la persona que llama:print(inspect.currentframe().f_back.f_code.co_name)
. Creo que debería ser más rápido ya que no recuperas una lista de todos los marcos de pila como loinspect.stack()
hace.inspect.currentframe().f_back.f_code.co_name
no funciona con un método decorado, mientrasinspect.stack()[0][3]
que ...Hay algunas formas de obtener el mismo resultado:
Tenga en cuenta que las
inspect.stack
llamadas son miles de veces más lentas que las alternativas:fuente
inspect.currentframe()
parece un buen compromiso entre el tiempo de ejecución y el uso de los miembros privados0.100 usec
o de0.199 usec
cualquier manera: cientos de veces más rápido que las opciones 1 y 2, comparable con la opción 4 (aunque Antony Hatchkins encontró la opción 3 tres veces más rápido que la opción 4).sys._getframe().f_code.co_name
másinspect.currentframe().f_code.co_name
simplemente porque ya he importado elsys
módulo. ¿Es esa una decisión razonable? (considerando que las velocidades parecen bastante similares)Puede obtener el nombre con el que se definió utilizando el enfoque que muestra @Andreas Jung , pero ese puede no ser el nombre con el que se llamó a la función:
Si esa distinción es importante para usted o no, no puedo decirlo.
fuente
.func_name
. Vale la pena recordar que los nombres de clase y los nombres de función en Python son una cosa y las variables que se refieren a ellos son otra.Foo2()
imprimirFoo
. Por ejemplo:Foo2 = function_dict['Foo']; Foo2()
. En este caso, Foo2 es un puntero de función para quizás un analizador de línea de comando.Quería algo muy similar porque quería poner el nombre de la función en una cadena de registro que iba en varios lugares en mi código. Probablemente no sea la mejor manera de hacerlo, pero aquí hay una forma de obtener el nombre de la función actual.
fuente
f
marco y elco
código. No lo uso tanto, así que mejor si solo loMantengo esta útil utilidad cerca:
Uso:
fuente
Supongo que
inspect
es la mejor manera de hacer esto. Por ejemplo:fuente
Encontré un contenedor que escribirá el nombre de la función
Esto imprimirá
fuente
my_funky_name.__name__
. Puede pasar la función .__ name__ a la función como un nuevo parámetro. func (* args, ** kwargs, my_name = func .__ name__). Para obtener el nombre de su decorador desde dentro de su función, creo que requeriría usar inspeccionar. Pero obtener el nombre de la función que controla mi función dentro de mi función de ejecución ... bueno, eso suena como el comienzo de un hermoso meme :)En realidad, esto se deriva de las otras respuestas a la pregunta.
Aquí está mi opinión:
La probable ventaja de esta versión sobre el uso de inspect.stack () es que debería ser miles de veces más rápido [vea la publicación y los horarios de Alex Melihoff sobre el uso de sys._getframe () versus el uso de inspect.stack ()].
fuente
print(inspect.stack()[0].function)
parece funcionar también (Python 3.5).fuente
Aquí hay un enfoque a prueba de futuro.
Combinar las sugerencias de @ CamHart y @ Yuval con la respuesta aceptada de @ RoshOxymoron tiene el beneficio de evitar:
_hidden
y métodos potencialmente obsoletosAsí que creo que esto funciona bien con futuras versiones de Python (probado en 2.7.3 y 3.3.2):
fuente
Prueba:
Salida:
fuente
No estoy seguro de por qué la gente lo complica:
fuente
En IDE el código sale
fuente
Puedes usar un decorador:
fuente
__name__
atributo de una función. El uso requiere saber lo que está tratando de obtener, lo que no me parece muy útil en casos simples donde las funciones no están definidas sobre la marcha.Hago mi propio enfoque utilizado para llamar a super con seguridad dentro del escenario de herencia múltiple (pongo todo el código)
muestra de uso:
probándolo:
salida:
Dentro de cada método decorado @with_name tiene acceso a self .__ fname__ como el nombre de la función actual.
fuente
Recientemente intenté usar las respuestas anteriores para acceder a la cadena de documentación de una función desde el contexto de esa función, pero como las preguntas anteriores solo devolvían la cadena de nombre, no funcionó.
Afortunadamente encontré una solución simple. Si, como yo, desea referirse a la función en lugar de simplemente obtener la cadena que representa el nombre, puede aplicar eval () a la cadena del nombre de la función.
fuente
Sugiero no confiar en los elementos de la pila. Si alguien usa su código dentro de diferentes contextos (por ejemplo, el intérprete de Python) su pila cambiará y romperá su índice ([0] [3]).
Te sugiero algo así:
fuente
Esto es bastante fácil de lograr con un decorador.
fuente