Or a broader question: how to make a recursive function in python and, when changing its name, it only has to be changed in the declaration?
Asked
Active
Viewed 2,159 times
9
-
Possible duplicate of [Can a lambda function call itself recursively in Python?](http://stackoverflow.com/questions/481692/can-a-lambda-function-call-itself-recursively-in-python) – metatoaster Oct 19 '15 at 02:17
-
why do you need to change the name of the function? You can do it but a lot of the time there is a better method than a dynamic function name. – LinkBerest Oct 19 '15 at 02:18
-
This is an interesting thought but I hope that in reality you're using a decent IDE or other tool to refactor safely rather than weird tricks like this. – Alex Hall Oct 19 '15 at 02:21
-
in reality i'm playing with python over SSH and i'm using vim – Oct 19 '15 at 02:30
-
2As a fan of long and descriptive function names it always annoyed me to repeat them inside themselves if the functions are recursive. It violates the DRY-principle. I think this problem should be addressed on code level an not be delegated to the IDE. It also makes can also make codesnippets more readable as the recursive character becomes obvious directly (one does not need to remember the function name). – cknoll Jun 07 '18 at 08:02
5 Answers
5
I found a simple, working solution.
from functools import wraps
def recfun(f):
@wraps(f)
def _f(*a, **kwa): return f(_f, *a, **kwa)
return _f
@recfun
# it's a decorator, so a separate class+method don't need to be defined
# for each function and the class does not need to be instantiated,
# as with Alex Hall's answer
def fact(self, n):
if n > 0:
return n * self(n-1) # doesn't need to be self(self, n-1),
# as with lkraider's answer
else:
return 1
print(fact(10)) # works, as opposed to dursk's answer
2
Here's an (untested) idea:
class Foo(object):
def __call__(self, *args):
# do stuff
self(*other_args)

Alex Hall
- 34,833
- 5
- 57
- 89
2
You can bind the function to itself, so it receives a reference to itself as first parameter, just like self
in a bound method:
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)
0
I don't know why you'd want to do this, but nonetheless, you can use a decorator to achieve this.
def recursive_function(func):
def decorator(*args, **kwargs):
return func(*args, my_func=func, **kwargs):
return decorator
And then your function would look like:
@recursive_function
def my_recursive_function(my_func=None):
...

Božo Stojković
- 2,893
- 1
- 27
- 52

dursk
- 4,435
- 2
- 19
- 30
0
disclaimer: dirty solution but no decorator needed
import sys
def factorial(x):
_f = eval(sys._getframe().f_code.co_name)
return x if x<3 else x*_f(x-1)
>>> factorial(5)
120

DPColombotto
- 159
- 1
- 3
- 11