Home > other >  keep track of how many class objects are created
keep track of how many class objects are created

Time:06-06

I want to create multiple objects and I want each object to keep track of the order it was created, so first object has id of 1, second id of 2 and so on.

class Something:
    id=0
    def __init__(self):
        Something.id =1

Currently I managed to keep track of the instances but not order. So

something1=Something()
something2=Something()

and if I call the id, both return 2

CodePudding user response:

In this case, the reason that both of the classes return an id of 2 is because you are incrementing the class variable instead of an instance specific variable.

You can instead make use of both to get proper ids, i.e. the following:

class Something:
    id=0
    def __init__(self):
        Something.id =1
        self.id = Something.id
        
something1=Something()
something2=Something()

print(something1.id, something2.id)

(this prints 1 2). The value of Something.id (the class variable) is also 2 in this case.

CodePudding user response:

Basically what you need is the class to count the number of instances of itself that are created, which could be used to set the value of an instance id attribute. The counting itself can be accomplished by applying the built-in next() function to an itertools.count() iterator object.

Also, since it's possible you may want to add this capability to multiple classes, implementing the instance-counting in a metaclass would make sense since doing so would allow it to easily be reused. Using a metaclass also insures that subclasses — i.e. class SomethingElse(Something): — will each have their own separate instance counters (instead of them all sharing the one in the baseclass as it would be in most of the other answers so far).

Here's what I'm suggesting:

from itertools import count


class InstanceCounterMeta(type):
    """Metaclass to maintain an instance count."""

    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)
        cls._instance_count = count(start=1)


class Something(metaclass=InstanceCounterMeta):
    def __init__(self):
        self.id = next(type(self)._instance_count)


something1 = Something()
something2 = Something()

print(something1.id)  # -> 1
print(something2.id)  # -> 2

CodePudding user response:

Just create an id member that isn't static:

class Something:
    id = 0

    def __init__(self):
        Something.id  = 1;
        self.id = Something.id


something1 = Something()
something2 = Something()

print(something1.id) # Prints 1
print(something2.id) # Prints 2

CodePudding user response:

If the goal of Something is more than keeping track of the instances you can separate this task and make it independently of it. The globals() built-in function is a dictionary which contains key-pair of "identifier-object". It is a dictionary so the insertion order is respected.

Note that it returns the state of when it is called, so if some objects are deleted they will not appear in the globals().

class A: pass

a1 = A()
a3 = A()
a2 = A()

# amount of instances
len(tuple(obj for obj in globals().values() if isinstance(obj, A)))
# 3

# object identifiers at this state of the program
(tuple(k for k, v in globals().items() if isinstance(v, A)))
# ('a1', 'a3', 'a2')

# delete an object
del a1
# new state
(tuple(k for k, v in globals().items() if isinstance(v, A)))
('a3', 'a2')

EDIT - implemented as class method

class A:

    @classmethod
    def instance_counter(cls):
        n = len(tuple(obj for obj in globals().values() if isinstance(obj, cls)))
        objs = ', '.join(tuple(k for k, v in globals().items() if isinstance(v, cls)))
        print(f'"{n}" instances of {cls.__name__} are in use: "{objs}"')

a1 = A()
a3 = A()
a2 = A()
A.instance_counter()
#"3" instances of A are in use: "a1, a3, a2"
  • Related