Counting instances of a class?

Question:

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?

Asked By: Blender

||

Answers:

You could consider using a class attribute to provide a counter. Each instance needs only to ask for the next value. They each get something unique. Eg:

from itertools import count

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

  def __init__(self):
    self.id = next(self._ids)
Answered By: g.d.d.c

Generator?

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

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)
Answered By: ratiotile

This should do the job:

class Obj:
    _counter = 0
    def __init__(self):
        Obj._counter += 1
        self.id = Obj._counter
Answered By: Andreas K.

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

Answered By: Jordan Russev
class InstanceCounter(object):
  # the instance counter
  counter = 0

  def __init__(self, val):
    self.val = all
    # incrementing every time an instance is created
    InstanceCounter.counter += 1

  def set_val(self, val):
    self.val = val

  def get_val(self, val):
    return self.val

  # accessing the instance counter should be done through a class method

  @classmethod
  def get_counter(cls):  
    return cls.counter

# See the instance counter as it increments as new instances are created
a=InstanceCounter(5)
print(a.get_counter())
b=InstanceCounter(7)
print(a.get_counter(), b.get_counter())
c=InstanceCounter(9)
print(a.get_counter(), b.get_counter(), c.get_counter())
Answered By: Nelson

You can use dir() function, which returns all properties and functions in the current script, to count the numbers of instances of a certain class.

len([i for i in dir() if isinstance(eval(i), ClassName)])
Answered By: Benjamin Wang
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.