# Function attributes

Wed Feb 10 19:31:23 CET 2010

```Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:

> On Wed, 10 Feb 2010 10:08:47 -0500, John Posner wrote:
>
>>> This won't work correctly, because old_f still tries to refer to itself
>>> under the name "f", and things break very quickly.
>>
>> They didn't break immediately for me -- what am I missing?:
>
> The original function f doesn't try to refer to itself in any way. With
> no recursive call or access, it doesn't matter what f is named.
>
>
>
>>>> def f(x):
> ...     if x < 0:
> ...             print "original"
> ...             return f(-x)
> ...     else:
> ...             return x+1
> ...
>>>> f(2)
> 3
>>>> f(-2)
> original
> 3
>>>>
>>>> old_f = f
>>>> def f(x):
> ...     if x > 0:
> ...             return old_f(-x)
> ...     else:
> ...             return x
> ...
>>>> f(-1)
> -1
>>>> f(1)
> original
> original
> original
> original
> original
> original
> [...]
>   File "<stdin>", line 3, in f
>   File "<stdin>", line 4, in f
>   File "<stdin>", line 3, in f
> RuntimeError: maximum recursion depth exceeded

It's not ideal, but you can use a decorator like this to solve this
problem:

def bindfunction(f):
def bound_f(*args, **kwargs):
return f(bound_f, *args, **kwargs)
bound_f.__name__ = f.__name__
return bound_f

>>> @bindfunction
... def factorial(this_function, n):
...     if n > 0:
...         return n * this_function(n - 1)
...     else:
...         return 1
...
>>> factorial(15)
1307674368000L
>>> fac = factorial
>>> fac(15)
1307674368000L
>>> factorial = 'foobar'
>>> fac(15)
1307674368000L

--
Arnaud

```