简体   繁体   中英

Listing all instance of a class

I wrote a Python module, with several classes that inherit from a single class called MasterBlock . I want to import this module in a script, create several instances of these classes, and then get a list of all the existing instances of all the childrens of this MasterBlock class. I found some solutions with vars()['Blocks.MasterBlock'].__subclasses__() but as the instances I have are child of child of MasterBlock , it doesn't work.

Here is some example code:

Module:

Class MasterBlock:
    def main(self):
        pass
Class RandomA(MasterBlock):
    def __init__(self):
        pass
    # inherit the main function
Class AnotherRandom(MasterBlock):
    def __init__(self):
        pass
    # inherit the main function

Script:

import module
a=module.RandomA()
b=module.AnotherRandom()
c=module.AnotherRandom()
# here I need to get list_of_instances=[a,b,c]

Th ultimate goal is to be able to do:

for instance in list_of_instances:
    instance.main()

What about adding a class variable, that contains all the instances of MasterBlock ? You can record them with:

Class MasterBlock(object):

    all_instances = []  # All instances of MasterBlock

    def __init__(self,…):
        …
        self.all_instances.append(self)  # Not added if an exception is raised before

You get all the instances of MasterBlock with MasterBlock.all_instances (or instance.all_instances ).

This works if all base classes call the __init__ of the master class (either implicitly through inheritance or explicitly through the usual super() call).

Here's a way of doing that using a class variable:

class MasterBlock(object):
    instances = []
    def __init__(self):
        self.instances.append(self)
    def main(self):
        print "I am", self

class RandomA(MasterBlock):
    def __init__(self):
        super(RandomA, self).__init__()
        # other init...

class AnotherRandom(MasterBlock):
    def __init__(self):
        super(AnotherRandom, self).__init__()
        # other init...


a = RandomA()
b = AnotherRandom()
c = AnotherRandom()
# here I need to get list_of_instances=[a,b,c]

for instance in MasterBlock.instances:
    instance.main()

(you can make it simpler if you don't need __init__ in the subclasses)

output:

I am <__main__.RandomA object at 0x7faa46683610>
I am <__main__.AnotherRandom object at 0x7faa46683650>
I am <__main__.AnotherRandom object at 0x7faa46683690>

If you add a __new__() method as shown below to your base class which keeps track of all instances created in a class variable, you could make the process more-or-less automatic and not have to remember to call something in the __init__() of each subclass.

class MasterBlock(object):
    instances = []
    def __new__(cls, *args, **kwargs):
        instance = super(MasterBlock, cls).__new__(cls, *args, **kwargs)
        instance.instances.append(instance)
        return instance

    def main(self):
        print('in main of', self.__class__.__name__)  # for testing purposes

class RandomA(MasterBlock):
    def __init__(self):
        pass
    # inherit the main function

class AnotherRandom(RandomA):  # works for sub-subclasses, too
    def __init__(self):
        pass
    # inherit the main function

a=RandomA()
b=AnotherRandom()
c=AnotherRandom()

for instance in MasterBlock.instances:
    instance.main()

Output:

in main of RandomA
in main of AnotherRandom
in main of AnotherRandom

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM