Recursive functions (was Re: Observations on the three pillars of Python execution)

Chris Angelico rosuav at gmail.com
Fri Aug 5 07:40:24 EDT 2011


On Fri, Aug 5, 2011 at 9:22 AM, Thomas Jollans <t at jollybox.de> wrote:
> On 05/08/11 09:20, Eric Snow wrote:
>> Object available during code object execution:
>> (M) no
>> (C) no
>> (F) no
> (F) yes.
>
> cf. recursion.

Is it? As I understand it, a Python function is not able to reference
"itself" but must reference its own name. This means that assigning
that function to something else stops it being recursive:

#####
>>> def foo(x):
	print(x)
	if x>3: foo(x-1)

>>> foo(5)
5
4
3
>>> bar=foo
>>> bar(5)
5
4
3
>>> def foo(x):
	print("Foo",x)
	if x>3: foo(x-1)

>>> foo(5)
Foo 5
Foo 4
Foo 3
>>> bar(5)
5
Foo 4
Foo 3
#####

bar() is not a recursive function, even though foo() was and is. I've
just played around with a decorator, though; this appears to work:

>>> def recursive(f):
	l=list(f.__defaults__)
	l[-1]=f
	f.__defaults__=tuple(l)
	return f
>>> @recursive
def quux(x,quux=None):
	print("Quux",x)
	if x>3: quux(x-1)
>>> foo=quux
>>> def quux(x):
	print("Stopping.")
>>> quux(5)
Stopping.
>>> foo(5)
Quux 5
Quux 4
Quux 3

Effectively, the decorator binds the function's own self to its last
default parameter, thus holding a cyclic reference (unlikely to be an
issue - people won't be creating and destroying functions frequently,
so GC issues shouldn't arise). The last parameter doesn't have to have
the name of the function; this works with lambdas:

>>> recursive(lambda x,_=None: print("Lambda",x) or (x>3 and _(x-1) or None))(5)
Lambda 5
Lambda 4
Lambda 3

Yes, this is a pretty stupid example. But is this sort of decorator
useful? It's not like people regularly want recursive lambdas.

Chris Angelico



More information about the Python-list mailing list