3

There is simple class:

class A(object): __COUNTER = 0 def do_something_1(self): ... def do_something_2(self): ... def do_something_N(self): ... 

Is there decision which can increase self.__COUNTER by calling method but not write it to each function?

I want as something as:

a = A() # COUNTER = 1 b = A() # COUNTER = 2 c = A() # COUNTER = 3 
5
  • Use a decorator: artima.com/weblogs/viewpost.jsp?thread=240808 Commented Jun 21, 2013 at 11:10
  • 2
    Your question now has become ambiguous. Did you want to increment the counter when creating a new instance or when calling methods on the instances? Your example implies the first, but the rest of your question asks for the latter! Commented Jun 21, 2013 at 11:15
  • I am sorry if wrote ambiguous. I want increase when new instance Commented Jun 21, 2013 at 11:19
  • could you explain me why you need this functionality? Commented Jun 21, 2013 at 11:30
  • It is huger issue. Need to exchange with remote server which restrict max connection. It must no more 5. I use Django, Celery and MongoDB and I attempts build decision that can would check for maximum connections Commented Jun 21, 2013 at 12:01

2 Answers 2

6

To hook into methods being called you'd have to use a decorator:

def increment_counter(method): def wrapper(self, *args, **kw): self._COUNTER += 1 return method(self, *args, **kw) return wrapper 

and apply this to each of the methods in your class:

class A(object): _COUNTER = 0 @increment_counter def do_something_1(self): ... @increment_counter def do_something_2(self): ... @increment_counter def do_something_N(self): ... 

Note that I renamed the counter to use one underscore, to avoid having to figure out the mangled name.

If you must have __COUNTER work (so with the double underscore), you could do that by passing in the name of the class:

def increment_counter(classname): counter_attribute = '_{}__COUNTER'.format(classname) def increment_counter_decorator(method): def wrapper(self, *args, **kw): setattr(self, counter_attribute, getattr(self, counter_attribute) + 1) return method(self, *args, **kw) return wrapper 

Then decorate the methods with:

@increment_counter('A') def do_something_1(self): ... 

If you wanted to create a counter per instance instead, simply add to the counter on the class:

class A(object): _COUNTER = 0 def __init__(self): A._COUNTER += 1 

or use type(self)._COUNTER if you want to use a separate counter per sub-class of A.

Sign up to request clarification or add additional context in comments.

2 Comments

Sadly - the update to the question has made this a lot simpler than the original question implied :(
Thanks for differents decisions.
3

Here's the simple version: How to increment a class-wide counter every time a particular function is called. The function can be __init__, which covers your specific question.

class cls(object): counter = 0 def __init__(self): self.__class__.counter += 1 print self.__class__.counter a = cls() # Prints 1 b = cls() # Prints 2 

As you can see, the trick is to increment self.__class__.counter, not self.counter. You can do that inside any member function.

But don't use names starting with a double underscore, because they have special meaning for python (unless you know and want the special meaning, of course). If you want to flag the counter as private, use a single underscore: _counter.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.