[Python-Dev] recursive closures - reference cycle

Kristján Valur Jónsson kristjan at ccpgames.com
Tue Dec 8 17:15:56 CET 2009


> -----Original Message-----
> From: python-dev-bounces+kristjan=ccpgames.com at python.org
> [mailto:python-dev-bounces+kristjan=ccpgames.com at python.org] On Behalf
> Of Antoine Pitrou
> Sent: 8. desember 2009 14:55
> To: python-dev at python.org
> Subject: Re: [Python-Dev] recursive closures - reference cycle
> 
> Kristján Valur Jónsson <kristjan <at> ccpgames.com> writes:
> >
> > The problem with this is that once you have called
> > factorial() once, you end up with a recursive cycle.
> 
> You don't need a closure to exhibit a reference cycle. A global
> function is
> enough:
> 
> >>> def helper(n):
> ...  if n:
> ...   return n*helper(n-1)
> ...  else:
> ...   return 1
> ...
> >>> helper.func_globals['helper'] is helper
> True
> 
yes, because:
func_globals is globals() == True

You don't need recursion for this to be true.  And as soon as you delete "helper" from globals() it goes away.
w = wearref.weakref(helper)
del helper
w() == False.

> 
> If you really want to avoid this you can prevent the function from
> depending
> on its outside environment:
> 
> >>> from functools import partial
> >>> def helper2(rec, n):
> ...  if n:
> ...   return n*rec(rec, n-1)
> ...  else:
> ...   return 1
> ...
> >>> factorial = partial(helper2, helper2)
> >>> "helper2" in factorial.func.func_globals
> True
> >>> del helper2
> >>> "helper2" in factorial.func.func_globals
> False
> >>> factorial(3)
> 6

Interesting, pass itself in as an argument.
Yes, there are ways around this, I know.  But you have to agree that it is unexpected, no?
Somethign for the "reference cycle FAQ."

Anyway, I´ll return to my lair now, thanks for your time python-dev :)

K


More information about the Python-Dev mailing list