编程语言
首页 > 编程语言> > Python:删除自引用对象

Python:删除自引用对象

作者:互联网

我想问一下如何在Python中删除具有自引用的对象.

让我们考虑一个类,这是一个简单的示例,它知道何时创建和删除它:

#!/usr/bin/python
class TTest:
  def __init__(self):
    self.sub_func= None
    print 'Created',self
  def __del__(self):
    self.sub_func= None
    print 'Deleted',self
  def Print(self):
    print 'Print',self

此类具有一个变量self.sub_func,我们假设要为其分配一个函数.我想将使用TTest实例的函数分配给self.sub_func.请参阅以下情况:

def SubFunc1(t):
  t.Print()
def DefineObj1():
  t= TTest()
  t.sub_func= lambda: SubFunc1(t)
  return t

t= DefineObj1()
t.sub_func()
del t

结果是:

Created <__main__.TTest instance at 0x7ffbabceee60>
Print <__main__.TTest instance at 0x7ffbabceee60>

也就是说,尽管我们执行了“ del t”,但并未删除t.

我猜想原因是t.sub_func是一个自引用对象,因此t的引用计数器在“ del t”处不会变为零,因此t不会被垃圾收集器删除.

为了解决这个问题,我需要插入

t.sub_func= None

在“ del t”之前;在这个时候,输出是:

Created <__main__.TTest instance at 0x7fab9ece2e60>
Print <__main__.TTest instance at 0x7fab9ece2e60>
Deleted <__main__.TTest instance at 0x7fab9ece2e60>

但这很奇怪. t.sub_func是t的一部分,所以我不想在删除t时担心清除t.sub_func.

您能否告诉我您是否知道一个好的解决方案?

解决方法:

如何确保引用循环中的对象不再不可访问时被删除?最简单的解决方案是不定义__del__方法.很少(如果有的话)的类需要__del__方法. Python无法保证何时或什至将调用__del__方法.

有几种方法可以缓解此问题.

>使用函数而不是包含并检查弱引用的lambda.每次调用函数时,都需要显式检查对象是否仍然存在.
>为每个对象创建一个唯一的类,以便我们可以将该函数存储在一个类上,而不是作为猴子修补函数.这可能会使内存变大.
>定义一个知道如何获取给定函数并将其转换为方法的属性.我个人最喜欢的是,它非常近似于如何从类的未绑定方法中创建绑定方法.

使用弱引用

import weakref

class TTest:
    def __init__(self):
        self.func = None
        print 'Created', self
    def __del__(self):
        print 'Deleted', self
    def print_self(self):
        print 'Print',self

def print_func(t):
    t.print_self()

def create_ttest():
    t = TTest()
    weak_t = weakref.ref(t)
    def func():
        t1 = weak_t()
        if t1 is None:
            raise TypeError("TTest object no longer exists")
        print_func(t1)
    t.func = func
    return t

if __name__ == "__main__":
    t = create_ttest()
    t.func()
    del t

创建一个独特的班级

class TTest:
    def __init__(self):
        print 'Created', self
    def __del__(self):
        print 'Deleted', self
    def print_self(self):
        print 'Print',self

def print_func(t):
    t.print_self()

def create_ttest():
    class SubTTest(TTest):
        def func(self):
            print_func(self)
    SubTTest.func1 = print_func 
    # The above also works. First argument is instantiated as the object the 
    # function was called on.
    return SubTTest()

if __name__ == "__main__":
    t = create_ttest()
    t.func()
    t.func1()
    del t

使用属性

import types

class TTest:
    def __init__(self, func):
        self._func = func
        print 'Created', self
    def __del__(self):
        print 'Deleted', self
    def print_self(self):
        print 'Print',self
    @property
    def func(self):
        return types.MethodType(self._func, self)

def print_func(t):
    t.print_self()

def create_ttest():
    def func(self):
        print_func(self)
    t = TTest(func)
    return t

if __name__ == "__main__":
    t = create_ttest()
    t.func()
    del t

标签:self-reference,python
来源: https://codeday.me/bug/20191028/1955429.html