[python] Determine el nombre de la función desde dentro de esa función (sin usar traceback)



7 Answers

import inspect

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

En Python, sin usar el módulo de traceback , ¿hay alguna manera 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 manera de que la barra sepa el nombre de la barra? O mejor aún, ¿el nombre de foo.bar ?

#foo.py  
def bar():
    print "my name is", __myname__ # <== how do I calculate this at runtime?



Puedes usar un decorador:

def my_function(name=None):
    return name

def get_function_name(function):
    return function(name=function.__name__)

>>> get_function_name(my_function)
'my_function'



import inspect

def whoami():
    return inspect.stack()[1][3]

def whosdaddy():
    return inspect.stack()[2][3]

def foo():
    print "hello, I'm %s, daddy is %s" % (whoami(), whosdaddy())
    bar()

def bar():
    print "hello, I'm %s, daddy is %s" % (whoami(), whosdaddy())

foo()
bar()

En IDE, el código de salida

hola, soy tonto, papi

hola, soy bar, papi es foo

hola, soy bar, papi




Esto se deriva de las otras respuestas a la pregunta.

Aquí está mi opinión:

import sys

# for current func name, specify 0 or no argument.
# for name of caller of current func, specify 1.
# for name of caller of caller of current func, specify 2. etc.
currentFuncName = lambda n=0: sys._getframe(n + 1).f_code.co_name


def testFunction():
    print "You are in function:", currentFuncName()
    print "This function's caller was:", currentFuncName(1)    


def invokeTest():
    testFunction()


invokeTest()

# end of file

La probable ventaja de esta versión sobre el uso de inspect.stack () es que debería ser miles de veces más rápida [consulte la publicación y los tiempos de Alex Melihoff sobre el uso de sys._getframe () versus el uso de inspect.stack ()].




Mantengo esta práctica utilidad cerca:

import inspect
myself = lambda: inspect.stack()[1][3]

Uso:

myself()



Hago mi propio enfoque usado para llamar al súper con seguridad dentro del escenario de herencia múltiple (pongo todo el código)

def safe_super(_class, _inst):
    """safe super call"""
    try:
        return getattr(super(_class, _inst), _inst.__fname__)
    except:
        return (lambda *x,**kx: None)


def with_name(function):
    def wrap(self, *args, **kwargs):
        self.__fname__ = function.__name__
        return function(self, *args, **kwargs)
return wrap

uso de muestra:

class A(object):

    def __init__():
        super(A, self).__init__()

    @with_name
    def test(self):
        print 'called from A\n'
        safe_super(A, self)()

class B(object):

    def __init__():
        super(B, self).__init__()

    @with_name
    def test(self):
        print 'called from B\n'
        safe_super(B, self)()

class C(A, B):

    def __init__():
        super(C, self).__init__()

    @with_name
    def test(self):
        print 'called from C\n'
        safe_super(C, self)()

probándolo:

a = C()
a.test()

salida:

called from C
called from A
called from B

Dentro de cada método decorado con @with_name tiene acceso a self .__ fname__ como el nombre de la función actual.




print(inspect.stack()[0].function) parece funcionar también (Python 3.5).




Puede obtener el nombre que se definió utilizando share , pero puede que ese no sea el nombre con el que se llamó a la función:

import inspect

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

Foo2 = Foo

>>> Foo()
Foo

>>> Foo2()
Foo

No puedo decir si esa distinción es importante para usted o no.




Related