Стек вызовов не сохраняет ссылку на саму функцию -
хотя бегущий кадр как ссылка на объект кода, который является кодом, связанным с данной функцией.
(Функции - это объекты с кодом и некоторой информацией об их среде, такие как замыкания, имя, глобальный словарь, строка документа, параметры по умолчанию и т. Д.).
Поэтому, если вы запускаете обычную функцию, вам лучше использовать ее собственное имя в глобальном словаре для вызова самого себя, как было указано.
Если вы используете какой-то динамический или лямбда-код, в котором вы не можете использовать имя функции, единственное решение состоит в том, чтобы перестроить другой объект-функцию, который повторно использует текущий запущенный объект кода, и вместо этого вызвать эту новую функцию.
Вы потеряете пару вещей, таких как аргументы по умолчанию, и может быть трудно заставить его работать с замыканиями (хотя это можно сделать).
Я написал сообщение в блоге о том, как именно - вызывать анонимные функции изнутри себя - надеюсь, что код там может вам помочь:
http://metapython.blogspot.com/2010/11/recursive-lambda-functions.html
С другой стороны: избегайте использования o inspect.stack - он слишком медленный, так как он перестраивает много информации при каждом вызове. вместо этого предпочтительнее использовать inspect.currentframe для работы с кадрами кода.
Это может показаться сложным, но сам код очень короткий - я вставлю его ниже. Пост выше содержит больше информации о том, как это работает.
from inspect import currentframe
from types import FunctionType
lambda_cache = {}
def myself (*args, **kw):
caller_frame = currentframe(1)
code = caller_frame.f_code
if not code in lambda_cache:
lambda_cache[code] = FunctionType(code, caller_frame.f_globals)
return lambda_cache[code](*args, **kw)
if __name__ == "__main__":
print "Factorial of 5", (lambda n: n * myself(n - 1) if n > 1 else 1)(5)
Если вам действительно нужна сама исходная функция, вышеприведенную функцию «я» можно сделать для поиска в некоторых областях (например, в глобальном словаре вызывающей функции) объекта функции, объект кода которого будет совпадать с объектом, извлеченным из фрейма. вместо создания новой функции.