Blender
Blender

Reputation: 298532

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?

Upvotes: 44

Views: 76431

Answers (9)

Bavenraj
Bavenraj

Reputation: 1

This could work as well if you want to count the number of instances in each class of specific variables. You can import pandas and read the data into the object.

object.variableName.value_counts()

This code will output the count of instances of each class within the specified variableName

Upvotes: -1

Margaret Hamilton
Margaret Hamilton

Reputation: 1

This Will do the job

class YourClass:
    counter = 0
    def __init__(self):
        YourClass.counter += 1 
    def PrintData(self):
        print(self.counter)

Upvotes: -1

g.d.d.c
g.d.d.c

Reputation: 48028

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)

Upvotes: 85

Benjamin Wang
Benjamin Wang

Reputation: 19

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)])

Upvotes: 1

Nelson
Nelson

Reputation: 1

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())

Upvotes: 0

Jordan Russev
Jordan Russev

Reputation: 77

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

Upvotes: 7

kuzand
kuzand

Reputation: 9806

This should do the job:

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

Upvotes: 31

ratiotile
ratiotile

Reputation: 963

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)

Upvotes: 8

jscs
jscs

Reputation: 64022

Generator?

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

Upvotes: 1

Related Questions