【问题标题】:Method call after garbage collection is finished垃圾回收完成后的方法调用
【发布时间】:2021-11-08 15:39:22
【问题描述】:

我有一个“Foo”类,其中的对象注册在一个名为 FooManager 的对象中。离开函数的范围后,只有当我知道所有“标记为删除”的 Foo 时,才能删除 Foo 对象。

class FooManager:
    
    def __init__(self):
        self.deletion_list = []
    
    def delete_tagged_foos(self):
        #Deletion process
        pass

class Foo:

    def __init__(self, FooManager):
        self.FooManager = FooManager

    def __del__(self):
        self.FooManager.deletion_list.append(self)

        if garbage_collection_finished():
            self.FooManager.delete_tagged_foos()


def foo_processing(manager):
    foo1 = Foo(manager)
    foo2 = Foo(manager)
    foo3 = Foo(manager)
    
    # Tag foo2 and foo3 for deletion (but not foo1)
    # and perform deletion process once every foo is tagged
    return foo1


manager = FooManager()

foo1 = foo_processing(manager)

如何获取布尔型garbage_collection_finished()?

【问题讨论】:

  • 为什么不在FooManager类中直接定义__del__()方法。只要有 Foo 的实例引用它,Python 就已经完成了保持 FooManager 实例活动的工作。
  • 我不明白这如何解决我的问题?在这个例子中,FooManager 的析构函数永远不会被调用
  • delete_tagged_foos 是做什么的?通常,您不需要自己进行任何垃圾收集。当一个对象的引用计数变为零时,它的内存就会被回收。垃圾收集只需要处理引用循环,其中两个(或更多)对象只能相互访问。
  • 我需要在量子信息的背景下解决这个问题。这里的细节在数学上很复杂且无关紧要。我关心的不是内存溢出,而是提供了一种方便的实现,可以自动执行在函数此时执行的繁琐任务。

标签: python garbage-collection destructor reference-counting


【解决方案1】:

为什么不直接在函数返回时自己调用方法:

foo1 = foo_processing(manager)
manager.delete_tagged_foos()

在调用delete_tagged_foos() 时,foo2foo3 都已向经理重新注册,因此不会再次被删除。

【讨论】:

  • 这将导致在每个处理 foo 的函数之后增加一行代码,没有经验的用户可能会忘记调用它。我宁愿避免这种情况。
  • 在 python 中没有办法做到这一点,除了引入其他东西来考虑刚刚“删除”一些实例。
【解决方案2】:

如何在 FooManager 中跟踪 foo 实例并将其用作创建临时 foo 实例的函数的装饰器:

import sys

class FooManager:
    
    def __init__(self):
        self.foos = []

    def registerFoo(self,foo):
        foo.FooManager = self
        self.foos.append(foo)
        print("+1")

    def cleanFoos(self,func):
        def callFunc(*args,**kwargs):
            result = func(*args,**kwargs)
            # 3 refs = self.foos, foo in comprehension, getrefcount param
            orphanFoos = [foo for foo in self.foos if sys.getrefcount(foo)<=3]
            # process orphans as needed
            # leave them in self.foos if they are not to be deleted
            self.foos  = [foo for foo in self.foos if foo not in orphanFoos]
            # ...
            print("foo count:",len(self.foos))
            return result 
        return callFunc
        
class Foo:

    def __init__(self, FooManager):
        FooManager.registerFoo(self)

    def __del__(self): print("deleted")

用法:

manager = FooManager()

@manager.cleanFoos
def foo_processing(manager):
    foo1 = Foo(manager)
    foo2 = Foo(manager)
    foo3 = Foo(manager)
    
    # Tag foo2 and foo3 for deletion (but not foo1)
    # and perform deletion process once every foo is tagged
    return foo1

foo1 = foo_processing(manager)

输出:

+1
+1
+1
foo count: 1
deleted
deleted

【讨论】:

  • 使用装饰器是一个了不起的想法!非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 2023-03-30
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多