如何获取当前模块中一个类的所有实例

3 投票
1 回答
4685 浏览
提问于 2025-04-16 20:46

我有一个模块叫做 foo,里面定义了一个类 Foo,并创建了好几个这个类的实例。

从其他模块中,我可以通过 import foo 来获取一个 Foo 对象的列表,方法是:

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

如果我能在模块 foo 内部也做到这一点就太好了。但是按照现在的写法,名字 foofoo 里面是没有意义的,换成 self 也没什么帮助。

有没有办法在这个模块内使用反射来找到这个类的所有实例呢?我希望能有一种方法,不用一个个地创建列表并添加每个实例。

1 个回答

8

目标: "import foo 并获取由...实例化的 Foo 对象列表"

其实你根本不需要反射功能。想象一下,这就是你的类:

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

演示;实例化一堆对象并引用它们:

>>> Registered()
>>> Registered()
>>> Registered()

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

因为你在使用 dir,如果我理解得没错,你是想找到当前模块的全局变量中的所有对象。不过,这样做其实并不能获取当前模块中的所有对象,只能找到那些绑定到变量上的对象。如果这正是你想要的,可以用 {var for name,var in globals() if isinstance(var,Foo)} 这个方法。

如果这不是你真正想要的,你可以修改上面的代码,通过 inspect.currentframe().f_back.f_globals 来追踪对象定义所在的模块,但这样会让你无法使用在 foo.py 或其他模块中定义的工厂函数。

不过,如果你实际上是想获取某个模块中创建的所有实例,这其实是一个严重的编码问题;你可以考虑在那个模块中写一个工厂函数包装器,这个包装器只负责传递初始化参数并返回结果,同时跟踪已初始化的对象。

撰写回答