Counting instances of a class?

I've been cleaning up some code from a module I'm extending and I can't seem to find a way to Pythonify this code:

global_next_id = 1

class Obj:
  def __init__(self):
    global global_next_id
    self.id = global_next_id

    global_next_id += 1

This code uses a global id to keep track of instances of a class (I need the variable self.id internally as well, and it needs to be a number).

Can anyone suggest a way to Pythonify this code?


Solution 1:

Try something like this:

from itertools import count

class Obj(object):
  _ids = count(0)

  def __init__(self):
    self.id = next(self._ids)

Solution 2:

This should do the job:

class Obj:
    _counter = 0
    def __init__(self):
        Obj._counter += 1
        self.id = Obj._counter

Solution 3:

Here is a way to count instances without descendant classes sharing the same id/count. A metaclass is used to create a separate id counter for each class.

Uses Python 3 syntax for Metaclasses.

import itertools

class InstanceCounterMeta(type):
    """ Metaclass to make instance counter not share count with descendants
    """
    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)
        cls._ids = itertools.count(1)

class InstanceCounter(object, metaclass=InstanceCounterMeta):
    """ Mixin to add automatic ID generation
    """
    def __init__(self):
        self.id = next(self.__class__._ids)

Solution 4:

I found the following solution:

class Obj:
    counter = 0

    def __init__(self):
        type(self).counter += 1

    def __del__(self):
        type(self).counter -= 1

It's better to use type(self).counter instead of Obj.counter

Solution 5:

Generator?

def get_next_id():
    curr_id = 1
    while True:
        yield curr_id
        curr_id += 1