Search code examples
pythonmoduleintrospection

How to obtain all instances of a class within the current module


I have a module foo that defines a class Foo, and instantiates a number of instances of this class.

From other modules, I can import foo and obtain a list of the Foo objects instantiated by:

[getattr(foo,f) for f in dir(f) if isinstance(getattr(foo,f), foo.Foo)]

It would be convenient if I could do this from within the module foo. But as written, the name foo is meaningless inside foo, and changing to self doesn't help.

Is there a way to use introspection within this module to find all instances of this class? I was hoping there was a way to avoid making a list and appending each instance.


Solution

  • goal: "import foo and obtain a list of the Foo objects instantiated by..."

    You don't need introspection at all. Imagine this is your class:

    class Registered(object):
        _all = set()
        def __init__(self):
            self.__class__._all.add(self)
    

    Demo; instantiate a bunch of objects and refer to them:

    >>> Registered()
    >>> Registered()
    >>> Registered()
    
    >>> Registered._all
    {<__main__.Registered object at 0xcd3210>, <__main__.Registered object at 0xcd3150>, <__main__.Registered object at 0xcd31d0>}
    

    Since you are using dir, if I understand you correctly, you are trying to find all the objects in the current module's global variables. However it doesn't really get you all the objects in the current module, only those bound to variables. If that's what you really want, you can do {var for name,var in globals() if isinstance(var,Foo)}

    If that's not what you really want, you can modify the above to keep track of the module the object was defined in via inspect.currentframe().f_back.f_globals or something, but this would prevent you from using factory functions defined in foo.py or in other modules.

    If you are actually trying to get all instances of something created in a module, this is a sign of a serious coding issue however; consider perhaps writing a factory function wrapper in that module, which does nothing except pass along the initialization args and return the result, keeping track of initialized objects.