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?
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)
Generator?
def get_next_id():
curr_id = 1
while True:
yield curr_id
curr_id += 1
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)
This should do the job:
class Obj:
_counter = 0
def __init__(self):
Obj._counter += 1
self.id = Obj._counter
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
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())
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)])
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?
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)
Generator?
def get_next_id():
curr_id = 1
while True:
yield curr_id
curr_id += 1
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)
This should do the job:
class Obj:
_counter = 0
def __init__(self):
Obj._counter += 1
self.id = Obj._counter
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
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())
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)])