__subclasses__() 是否被缓存?

Is __subclasses__() cached?

我在三个不同的文件中有三个模型。 模块都在sys.path

a.py:
class A(object):
    pass

b.py:
class B(A):
    passs

c.py:
class C(A):
    pass

现在我想得到A的子类:

print A.__subclasses__()
>> [<class 'b.B'>, <class 'c.C'>]

到目前为止一切顺利。 但是现在我从 sys.path 中删除 c.py 并再次获取子类。我会例外,只剩下 B 了。 但是输出是一样的:

# remove c.py from sys.pyth
sys.path.remove('../c')
print A.__subclasses__()
>> [<class 'b.B'>, <class 'c.C'>]

因此 __subclasses__ 调用以某种方式被缓存。 是否可以强制__subclasses__再次搜索sys.path?

不,class.__subclasses__() 没有缓存,不是真的;内部实现使用弱引用。但是 modules 是;删除 c.py 文件不会卸载模块。

您也必须删除该模块:

import sys

del sys.modules['c']

并确保没有对该模块的其他引用。

因为 classes 本身涉及很多引用(他们指向他们的基础 classes,首先)你需要确保你 运行 gc.collect()确保已删除的 class 个对象不再保留在内存中:

>>> class B(A): pass
... 
>>> A.__subclasses__()
[<class '__main__.B'>]
>>> del B
>>> A.__subclasses__()
[<class '__main__.B'>]
>>> gc.collect(0)
0
>>> gc.collect(1)
3
>>> gc.collect(1)
0
>>> gc.collect(2)
0
>>> A.__subclasses__()
[]

您的示例不完整,不幸的是,您遗漏的部分是最重要的。让我纠正你的例子:

a.py:

class A(object):
    pass

b.py:

from a import A    # you left this out
class B(A):
    passs

c.py:

from a import A    # you left this out
class C(A):
    pass

一旦你import一个模块,它仍然是导入的,除非你明确地卸载它。修改 sys.path 不会影响加载模块集。