Question

I have class in Python which I need to use as a decorator class but I want to count something when it is called:

class SomeClass:

    counter = 0

    @staticmethod
    def some_function(a):
        """
        -----------------------
        Does something
        -----------------------
        """
        SomeClass.counter += 1
        a = a * a
        return a

after calling:

a = new_var.some_function(a) 

how do I then get the counter value from my decorator class?

Was it helpful?

Solution

The class you have shown us is not a decorator -- it is simply a class. Accessing the counter is as easy as

SomeClass.counter
# current counter value

Making your class an actual decorator is not difficult -- I'll rename it to Counter, however.

class Counter:
    """
    Count the number of calls made to the wrapped function.
    """
    def __init__(self, func):
        self.counter = 0
        self.func = func
    def __call__(self, *args, **kwds):
        self.counter += 1
        return self.func(*args, **kwds)

@Counter
def square(n):
    return n * n

and in use:

square(3)
# 9
square(7)
# 41
square(11)
# 121

square.counter
# 3

Note: This is a very simple decorator, and one side-effect is that the signature of the wrapped function is lost.

the unwrapped signature:

Help on function square in module __main__:
square(n)

the wrapped signature:

Help on instance of Counter in module __main__:
class Counter
 |  Count the number of calls made to the wrapped function.
 |  
 |  Methods defined here:
 |  
 |  __call__(self, *args, **kwds)
 |  
 |  __init__(self, func)

OTHER TIPS

I guess it depends on how you want to count. For example:

>>> class A(object):
>>>     pass
>>> ...
>>> def foo(obj):
>>>     def inner(*args, **kwargs):
>>>         counter += 1
>>>         print "times called: %d" % counter
>>>     counter = 0
>>>     return inner

>>> Bar = A()
>>> Bar.eggs = foo(Bar)
>>> Bar.foo()
times called: 1
>>> Bar.foo()
times called: 2
>>> Spam = A()
>>> Spam.eggs = foo(Spam)
>>> Spam.eggs()
times called: 1

This works because the wrapper will carry its environment around with it, which means counter is in scope of any given instance of an_object.foo when it is wrapped. Though it may not be as introspective as you would need. Or, do you mean to count the total number of times obj.foo is actually called?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top