9

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?

5
  • Possible duplicate of Can a lambda function call itself recursively in Python? Commented Oct 19, 2015 at 2: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. Commented Oct 19, 2015 at 2: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. Commented Oct 19, 2015 at 2:21
  • in reality i'm playing with python over SSH and i'm using vim Commented Oct 19, 2015 at 2:30
  • 3
    As 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). Commented Jun 7, 2018 at 8:02

5 Answers 5

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
Sign up to request clarification or add additional context in comments.

Comments

2

Here's an (untested) idea:

class Foo(object):

    def __call__(self, *args):
        # do stuff
        self(*other_args)

Comments

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)

Source: https://stackoverflow.com/a/5063783/324731

Comments

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

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.