Есть ли общий способ для функции ссылаться на себя? - PullRequest
28 голосов
/ 21 февраля 2011

Я могу получить доступ к атрибуту функции Python внутри самой функции по следующему коду:

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

Однако, если выше aa(), функция является шаблоном для написания другого кода, скажем, bb(), у меня естьнаписать:

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

Есть ли "указатель", похожий на аргумент self в методе класса, чтобы я мог написать такой код?

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

Я искал и нашелкто-то сказал использовать класс для решения этой проблемы, но это может быть проблемой для переопределения всех существующих функций.Есть предложения?

Ответы [ 3 ]

27 голосов
/ 21 февраля 2011

Не существует общего способа для функции ссылаться на себя.Попробуйте вместо этого использовать декоратор.Если все, что вы хотели, как вы указали, это напечатать информацию о функции, которую можно легко сделать с помощью декоратора:

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

Если вам действительно нужно ссылаться на функцию, просто добавьте ее к аргументам функции:

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

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

Редактировать, чтобы добавить альтернативный декоратор :

Вы также можете написать более простой (и, возможно, более быстрый) декоратор, который обеспечит корректную работу упакованной функции с Python.introspection:

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!

Это использует протокол дескриптора Python: у функций есть метод __get__, который используется для создания связанных методов.Декоратор просто использует существующий метод, чтобы сделать функцию связанным методом самого себя.Он будет работать только для автономных функций, если вы хотите, чтобы метод мог ссылаться на себя, вам пришлось бы делать что-то более похожее на оригинальное решение.

12 голосов
/ 21 февраля 2011

http://docs.python.org/library/inspect.html выглядит многообещающе:

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

Вы также можете использовать модуль sys, чтобы получить название текущей функции:

import sys
def bar():
     felf = globals()[sys._getframe().f_code.co_name]
     print felf.__name__, felf.__doc__
0 голосов
/ 07 августа 2012

Как насчет быстрого взлома, чтобы сделать свое собственное имя, например:

>>> 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>
>>>
...