How to create a (transparent) decorator with status information?

Timo Schmiade the_isz at gmx.de
Mon Apr 18 08:47:02 EDT 2011


Hi all,

I'm currently occupying myself with python's decorators and have some
questions as to their usage. Specifically, I'd like to know how to
design a decorator that maintains a status. Most decorator examples I
encountered use a function as a decorator, naturally being stateless.

Consider the following:

def call_counts(function):
  @functools.wraps(function):
  def wrapper(*args, **kwargs):
    # No status, can't count #calls.
    return function(*args, **kwargs)
  return wrapper

Thinking object-orientedly, my first idea was to use an object as a
decorator:

class CallCounter:
  def __init__(self, decorated):
    self.__function = decorated
    self.__numCalls = 0

  def __call__(self, *args, **kwargs):
    self.__numCalls += 1
    return self.__function(*args, **kwargs)

  # To support decorating member functions
  def __get__(self, obj, objType):
    return functools.partial(self.__call__, obj)

This approach however has three problems (let "decorated" be a function
decorated by either call_counts or CallCounter):

* The object is not transparent to the user like call_counts is. E.g.
  help(decorated) will return CallCounter's help and decorated.func_name
  will result in an error although decorated is a function.
* The maintained status is not shared among multiple instances of the
  decorator. This is unproblematic in this case, but might be a problem
  in others (e.g. logging to a file).
* I can't get the information from the decorator, so unless CallCounter
  emits the information on its own somehow (e.g. by using print), the
  decorator is completely pointless.

So, my question is: What would the "pythonic" way to implement a
decorator with status information be? Or am I missing the point of
decorators and am thinking in completely wrong directions?

Thanks in advance!

Kind regards,

Timo



More information about the Python-list mailing list