How can I increase counter properties of class when a instance is called?

前端 未结 2 2037
余生分开走
余生分开走 2021-01-20 13:02

There is simple class:

class A(object):

    __COUNTER = 0

    def do_something_1(self):
        ...

    def do_something_2(self):
        ...         


        
相关标签:
2条回答
  • 2021-01-20 13:31

    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.

    0 讨论(0)
  • 2021-01-20 13:40

    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.

    0 讨论(0)
提交回复
热议问题