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