Skip to content Skip to sidebar Skip to footer

Tracking Number Of Function Calls + Closures (à La Sicp) In Python

This is a question about scope and closures in Python, motivated by an exercise in SICP. Much thanks for your time if you read this! A question (3.2) in SICP asks one to create a p

Solution 1:

I think writing a decorator wrapping the function in a class would be more pythonic:

from functools import wraps 

defmake_monitored(func):
    classwrapper:
        def__init__(self, f):
            self.func = f
            self.counter = 0def__call__(self, *args, **kwargs):
            self.counter += 1return self.func(*args, **kwargs)
    return wraps(func)(wrapper(func))

This has the advantage that it mimics the original function as close as possible, and just adds a counter field to it:

In [25]: msqrt = make_monitored(math.sqrt)
In [26]: msqrt(2)
Out[26]: 1.4142135623730951
In [29]: msqrt.counter
Out[29]: 1
In [30]: msqrt(235)
Out[30]: 15.329709716755891
In [31]: msqrt.counter
Out[31]: 2
In [32]: @make_monitored
    ...: deff(a):
    ...:     """Adding the answer"""
    ...:     return a + 42
In [33]: f(0)
Out[33]: 42
In [34]: f(1)
Out[34]: 43
In [35]: f.counter
Out[35]: 2
In [36]: f.__name__
Out[36]: 'f'
In [37]: f.__doc__
Out[37]: 'Adding the answer'

For f, you also see the usage as a decorator, and how the wrapper keeps the original name and docstring (which would not be the case without functools.wraps).

Defining reset is left as an exercise to the reader, but quite trivial.

Post a Comment for "Tracking Number Of Function Calls + Closures (à La Sicp) In Python"