我有一个单例类,我不明白Python垃圾收集器是如何不删除实例的
我正在使用-from singleton_decorator导入singleton
我的班级示例:
from singleton_decorator import singleton
@singleton
class FilesRetriever:
def __init__(self, testing_mode: bool = False):
self.testing_mode = testing_mode
测试示例:
def test_singletone(self):
FilesRetriever(testing_mode=True)
mode = FilesRetriever().testing_mode
print("mode 1:" + str(mode))
mode = FilesRetriever().testing_mode
print("mode 2:" + str(mode))
count_before = gc.get_count()
gc.collect()
count_after = gc.get_count()
mode = FilesRetriever().testing_mode
print("mode 3:" + str(mode))
print("count_before:" + str(count_before))
print("count_after:" + str(count_after))
测试输出:
mode 1:True
mode 2:True
mode 3:True
count_before:(306, 10, 5)
count_after:(0, 0, 0)
我希望在垃圾收集器自动运行或在测试中运行它之后,_SingletonWrapper(decorator实现中的类)的实例将被删除,因为没有任何对象指向它。然后“print”(“mode 3:“+str(mode))”的值将为False,因为这是默认值(实例已重新创建)
因此,代码和垃圾收集工作正常。请看您所指的单例装饰器的代码decorator
仅仅因为您调用了
gc.collect()
,并且您的代码没有在某处保存引用,并不意味着其他代码没有在decorator中,它创建一个实例,然后将该实例存储在decorator中的一个变量中。因此,即使您收集了与代码相关的数据。他们的代码仍然持有对该实例的引用,因此无法收集该实例
这是单身汉的预期行为,因为这是它的全部目的。是将实例存储在可以检索和使用的地方,而不是每次都创建一个新实例。因此,除非需要替换该实例,否则您不会希望该实例被丢弃
回答您的评论
不,您没有将实例获取到
_SingletonWrapper
。当您编写FileRetriever()
时,您实际上正在调用_SingletonWrapper
实例的__call__
方法。使用@singleton()
返回实例而不是类对象时同样,在代码中,您不将其存储在任何地方并不意味着它不存储在其他地方。当您定义一个类时,您所做的在某种意义上是在模块的全局范围内,它正在创建一个保存该类定义的变量。所以在全局范围内的代码中,它是这样的
现在,类定义存储在变量调用
FileRetriever
中现在您使用的是一个装饰器,看起来是基于单个装饰器中的代码
现在您可以看到类被包装并存储在变量
FileRetriever
中。 现在,在运行FileRetriever()
时调用_SingletonWrapper.__call__()
。 因为__call__
是一个实例方法。它可以保存对您的原始类和您声明的类的实例的引用,因此即使您删除了对该类的所有引用,该代码仍然保留该引用如果你真的想删除所有关于你是单身汉的引用,我不知道你为什么会这么做。您需要删除对包装器的所有引用以及您的类。因此
FileRetriever = None
之类的内容可能会导致gc收集它。但在这个过程中,您将失去原始的类定义相关问题 更多 >
编程相关推荐