¿Hay una forma genérica para que una función se haga referencia a sí misma?


Puedo acceder al atributo de una función python dentro de la propia función mediante el siguiente código:

def aa():
    print aa.__name__
    print aa.__hash__
    # other simliar

Sin embargo, si la función above aa() es una plantilla para escribir otro código, digamos bb(), tengo que escribir:

def bb():
    print bb.__name__
    print bb.__hash__
    # other simliar

¿Hay un "puntero" similar al argumento self en un método de clase para que pueda escribir código como este?

def whatever():
    print self.__name__
    print self.__hash__
    # other simliar

Busqué y encontré a alguien que dijo que usara la clase para resolver este problema, pero eso puede ser un problema para redefinir todas las funciones existentes. Cualquier sugerencias?

Author: martineau, 2011-02-21

3 answers

No existe una forma genérica para que una función se refiera a sí misma. Considere usar un decorador en su lugar. Si todo lo que quieres como indicaste es imprimir información sobre la función que se puede hacer fácilmente con un decorador:

from functools import wraps
def showinfo(f):
    @wraps(f)
    def wrapper(*args, **kwds):
         print(f.__name__, f.__hash__)
         return f(*args, **kwds)
    return wrapper

@showinfo
def aa():
    pass

Si realmente necesita hacer referencia a la función, simplemente agréguela a los argumentos de la función:

def withself(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        return f(f, *args, **kwds)
    return wrapper

@withself
def aa(self):
      print(self.__name__)
      # etc.

Editar para añadir decorador alternativo :

También puede escribir un decorador más simple (y probablemente más rápido) que hará que el envuelto la función funciona correctamente con la introspección de Python:

def bind(f):
    """Decorate function `f` to pass a reference to the function
    as the first argument"""
    return f.__get__(f, type(f))

@bind
def foo(self, x):
    "This is a bound function!"
    print(self, x)


>>> foo(42)
<function foo at 0x02A46030> 42
>>> help(foo)
Help on method foo in module __main__:

foo(self, x) method of builtins.function instance
    This is a bound function!

Esto aprovecha el protocolo descriptor de Python: las funciones tienen un método __get__ que se usa para crear métodos enlazados. El decorador simplemente utiliza el método existente para hacer que la función sea un método enlazado de sí mismo. Solo funcionará para funciones independientes, si desea que un método sea capaz de hacer referencia a sí mismo, tendría que hacer algo más parecido a la solución original.

 25
Author: Duncan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-27 10:07:10

Http://docs.python.org/library/inspect.html parece prometedor:

import inspect
def foo():
     felf = globals()[inspect.getframeinfo(inspect.currentframe()).function]
     print felf.__name__, felf.__doc__

También puede usar el módulo sys para obtener el nombre de la función actual:

import sys
def bar():
     felf = globals()[sys._getframe().f_code.co_name]
     print felf.__name__, felf.__doc__
 10
Author: akira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-21 11:00:22

¿Qué tal un hackeo rápido para hacer su propio" auto " nombre, como este:

>>> def f():
...     self = f
...     print "My name is ", self.__name__, "and I am", self.__hash__
...
>>> f()
My name is  f and I am <method-wrapper '__hash__' of function object at 0x00B50F30>
>>> x = f
>>> x()
My name is  f and I am <method-wrapper '__hash__' of function object at 0x00B50F30>
>>>
 -3
Author: Steve Ferg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-07 14:24:10