Function attributes

Arnaud Delobelle arnodel at googlemail.com
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.
>
> See this example  instead:
>
>
>>>> 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



More information about the Python-list mailing list