getrecursiondepth
Manlio Perillo
NOmanlio_perilloSPAM at libero.it
Thu Sep 30 13:59:04 EDT 2004
On Tue, 28 Sep 2004 16:26:16 GMT, Andrew Dalke <adalke at mindspring.com>
wrote:
>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.
You are right. Thanks.
>
>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
> >>>
>
No, I don't want this. "Hello!" should be printed every times.
Here is a functions that returns True if the caller's 'recursion
depth' is 1.
Please check if this is correct.
>>> def firstlevel_call():
return sys._getframe(1).f_code != sys._getframe(2).f_code
N.B.: sys._getframe(2) can raise an exception
An example:
>>> def foo(n = 0):
print firstlevel_call()
print 'n =', n
if n == 5: return
foo(n + 1)
>>> foo()
True
n = 0
False
n = 1
False
n = 2
False
n = 3
False
n = 4
False
n = 5
Using firstlevel_call one can 'rescale' the getrecursiondepth
function.
Here is the correct pystate module:
---------------------------
from _pystate import getrecursiondepth as _getrecursiondepth
_recursion_base = 0
def rescale(depth = None):
global _recursion_base
if depth is None:
_recursion_base = _getrecursiondepth()
else:
_recursion_base = depth
def getrecursiondepth():
return _getrecursiondepth() - _recursion_base
---------------------------
And here is an example:
>>> def foo(n = 0):
if firstlevel_call():
pystate.rescale()
print 'n = %s, recursion depth = %s' % (n,
pystate.getrecursiondepth())
if n == 5: return
foo(n + 1)
>>> foo()
n = 0, recursion depth = 0
n = 1, recursion depth = 1
n = 2, recursion depth = 2
n = 3, recursion depth = 3
n = 4, recursion depth = 4
n = 5, recursion depth = 5
>> 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)
>
Sorry, I don't understand.
Here is my_function:
def my_function(a, b, *args, **kwargs):
print 'a, b, args, kwargs:', a, b, args, kwargs
Thanks and regards Manlio Perillo
More information about the Python-list
mailing list