getrecursiondepth

Andrew Dalke adalke at mindspring.com
Tue Sep 28 12:26:16 EDT 2004


Manlio Perillo wrote:
>>>1) To write code that execute once in a function (as C static
>>>variables)
>>>2) To guard against too many recursion

> def spam(x):
> 	if getrecursiondepth() == 1:
> 		# initialization code
> 
> This is equivalent to C++ code:
> 
> struct Init
> {
> Init() { /* initialization code */ }
> };
> 
> void spam(int x)
> {
> 	static Init init;
> 	...
> }

No, it isn't.  It requires that spam() be called from
the top-level code.  But what if it's called from
the unittest framework?  Then the depth will be lower.

Try this as a alternate solution for your style
of use.  It's still not the right one because it
doesn't handle reloads nor multiple functions
created through exec's.

_firsttime_db = {}
def firsttime():
   frame = sys._getframe(1)
   tag = (frame.f_lineno, frame.f_code.co_filename)
   if tag in _firsttime_db:
     return 0
   _firsttime_db[tag] = 1
   return 1

 >>> def spam():
...   if firsttime():
...     print "Hello!"
...   print "called"
...
 >>> spam()
Hello!
called
 >>> spam()
called
 >>> spam()
called
 >>>

You could make it a bit safer with

import weakref
_firsttime_dict = weakref.WeakKeyDictionary()
def firsttime(obj):
   if obj in _firsttime_dict:
     return 0
   _firsttime_dict[obj] = 0
   return 1

def spam():
   if firsttime(spam):
     print "Hello"
   print "called"


> I have already used this 'pattern'.
> But sometimes I don't want to expose the 'limit' on the argument list.
> Actually I have resolved this by doing:
> 
> def my_function(x, y, z, __max_depth = 20)
> 
> But this means I can't use keyword argument in my function!

then do

def _my_function(x, y, z, __maxdepth = 20):
   .. do your recursive code here ..

def my_function(x, y, z):
   return _my_function(x, y, z)

How would you solve this problem using your stack depth
function?  Any solution I come up with is more
complicated than what I just showed here and is no
longer thread safe.

> This is not a problem!.
> getrecursiondepth is not intended for such things.
   ...
> Ok, but remember the Python paradigm: we are adult programmers...

As an adult I still don't know what you would want
to use this value.  The first example you give
(static init) fails if someone looks at it funny.
I'm adult, but I can't be that cautious.  The second
example (recursion), well I just don't see how knowing
the depth makes the code any easier to write or clearer
to understand.

> Anyway I have asked why getrecursiondepth is not included in sys
> module because many members of the PyThreadState struct are accessible
> from Python.

Maybe they're useful?

				Andrew
				dalke at dalkescientific.com



More information about the Python-list mailing list