有没有办法在python中引用当前函数?

Ela*_*zar 1 python

我想要一个函数来引用它自己.例如,是递归的.

所以我做了类似的事情:

def fib(n):
    return n if n <= 1 else fib(n-1)+fib(n-2)
Run Code Online (Sandbox Code Playgroud)

这在大多数时候都很好,但fib实际上并不是指自己; 它指的是fib封闭块中的绑定.因此,如果由于某种原因fib被重新分配,它将会破坏:

>>> foo = fib
>>> fib = foo(10)
>>> x = foo(8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fib
TypeError: 'int' object is not callable
Run Code Online (Sandbox Code Playgroud)

fib如果可能的话,我怎样才能防止这种情况发生(从内部)?据我所知,在fib完全执行函数定义之前,名称不存在; 有没有解决方法?

我没有真正可能发生的实际用例; 我只是出于纯粹的好奇心.

Abe*_*lus 6

我会为此做一个装饰师

from functools import wraps

def selfcaller(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(wrapper, *args, **kwargs)
    return wrapper
Run Code Online (Sandbox Code Playgroud)

并使用它

@selfcaller
def fib(self, n):
    return n if n <= 1 else self(n-1)+self(n-2)
Run Code Online (Sandbox Code Playgroud)

这实际上是定义固定点组合器(或Y组合器)的可读方式:

fix = lambda g: (lambda f: g(lambda arg: f(f)(arg))) (lambda f: g(lambda arg: f(f)(arg)))
Run Code Online (Sandbox Code Playgroud)

用法:

fib = fix(lambda self: lambda n: n if n <= 1 else self(n-1)+self(n-2))
Run Code Online (Sandbox Code Playgroud)

要么:

@fix
def fib(self):
    return lambda n: n if n <= 1 else self(n-1)+self(n-2)
Run Code Online (Sandbox Code Playgroud)

这里的绑定发生在形式参数中,因此不会出现问题.