'Create an incremental ID in a Python class with subclasses each maintaining their own ID series
I want to create a class wherein each object of the class is given a unique sequential ID starting at 0. I also want each subclass to have sequential IDs starting at 0 as well, with numbering unaffected by parent or sibling classes.
Using the answer to a similar question, I've created the class Foo
class Foo:
id_iter = itertools.count()
def __init__(self):
self.id = next(self.id_iter)
All instances of Foo will have a sequential id value. I also want to create a class Bar that inherits from Foo such that
>>> Foo().id
0
>>> Foo().id
1
>>> Foo().id
2
>>> Bar().id # The first Bar id starts at 0 rather than 3
0
If I create Bar like:
class Bar(Foo):
def __init__(self):
super(Bar, self).__init__()
The above call to Bar().id would return 3 because both classes are using the same iterator. Alternatively, I could add id_iter = itertools.count() back into my Bar definition and get the output I'm expecting. However, I'm making multiple subclasses of Foo, and don't want to have to add that line to each class; I want all subclasses of Foo to automatically inherit the ID functionality without having to add anything extra to the subclass definition. How can I achieve this?
Solution 1:[1]
You can't do this with a class attribute as class attributes are not inherited. One method could be to use a separate dictionary for keeping count of classes. For example:
import itertools
class ClassCounter(object):
counters = {}
@classmethod
def get_counter(cls, class_to_count):
cls.counters.setdefault(class_to_count, itertools.count())
return next(cls.counters[class_to_count])
class Foo:
def __init__(self):
self.id = ClassCounter.get_counter(self.__class__)
class Bar(Foo):
def __init__(self):
super(Bar, self).__init__()
if __name__ == '__main__':
foo1 = Foo()
foo2 = Foo()
foo3 = Foo()
bar1 = Bar()
bar2 = Bar()
print(f"{foo1.id=}, {foo2.id=}, {foo3.id=}, {bar1.id=}, {bar2.id=}")
This should print:
foo1.id=0, foo2.id=1, foo3.id=2, bar1.id=0, bar2.id=1
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Selcuk |
