我想删除所有引用一个内存位置的对象。如果我不知道他们的全名怎么办呢?
class Foo(object):
pass
class Bar(object):
pass
a = Foo()
b = a
c = Bar()
c.a_ref = a
c.b_ref = b
for item in a, b, c.a_ref, c.b_ref:
print(id(item))
""" Out:
140035270075472
140035270075472
140035270075472
140035270075472
"""
UPD:
确定。我想删除link
或port1.link
并且不要担心链接到它的所有其他端口(port2.link
),它们也必须消失。
class LINK(object):
pass
class PORT(object):
def __init__(self, link=None):
self.link = link
def __repr__(self):
return str(id(self.link))
link = LINK()
port1 = PORT()
port2 = PORT()
port1.link = port2.link = link
print(id(link), port1, port2)
# (140586778512720, 140586778512720, 140586778512720)
del link
print(port1, port2)
# (140586778512720, 140586778512720)
# want: (None, None) ???
答案 0 :(得分:3)
您无法在Python中明确释放内存。垃圾收集器负责为您完成此操作。
您可以做的是保证清除对象的所有引用。垃圾收集器使用时期(如e1,e2和e3),只有e3中的对象将在下一次迭代中清除。
如果没有对它们的引用,对象只从epoch eX到eY(其中Y> X)。所以你的对象从e1开始;如果你"清洁"所有引用,在垃圾收集器的下一次迭代中,它们将被移动到e2;在下一个中,他们将被移动到e3,最后将释放内存。
您可以更改调用垃圾收集器的周期,但我不建议这样做。或者您可以使用gc.collect()
强制调用垃圾收集器,但正如我所说,您的对象必须在清除之前经历所有时期(这就是为什么调用gc.collector()
没有&#39} ;为你工作)。只是为了澄清,一旦达到阈值(gc跟踪的内存中的对象数量),就会调用垃圾收集器。
如果你想在Python中诊断内存泄漏,你也可以使用非常好的objgraph
库。它使用对象之间的所有链接和引用构建图形,并允许您识别周期。当您认为清除所有引用时,循环是垃圾收集器不释放对象的主要原因。这是一个很好的教程http://chase-seibert.github.io/blog/2013/08/03/diagnosing-memory-leaks-python.html
答案 1 :(得分:1)
您无法明确释放内存。您需要做的是确保不要保留对象的引用。然后他们将被垃圾收集,释放内存。
顺便说一下,你可以调用gc.collect()
强制执行gc操作。
<强>更新强>
您不能通过仅删除其中一个引用来删除对一个对象的所有引用,因为您不知道还有哪些人仍在使用此对象。如果是这样,还会有另一个问题,如何在不承认我的情况下阻止他人删除我的对象。
我认为您问题的最佳解决方案是单独删除属性链接。
del link
del port1.link
del port2.link
然后在删除后获取无,你应该这样做:
...
def __repr__(self):
repr_string = getattr(self, 'link', None)
return str(id(self.link)) if repr_string else None
...
答案 2 :(得分:1)
请参阅weakref模块。它维护对对象的引用,但如果删除了所有强引用,则不会阻止对象进行垃圾回收。例如:
import weakref
class LINK(object):
pass
class PORT(object):
def __init__(self, link=None):
if link is not None:
self.link = weakref.ref(link)
else:
self.link = None
def __repr__(self):
if self.link is None:
return 'None'
o = self.link()
return 'None' if o is None else str(id(o))
link = LINK()
port1 = PORT()
port2 = PORT()
port1.link = port2.link = weakref.ref(link)
print(id(link), port1, port2)
del link
print(port1, port2)
输出:
70741240 70741240 70741240
None None
注意,在弱引用报告gc.collect()
之前,您可能仍需要在某些情况下致电None
。
答案 3 :(得分:1)
对我来说,你真正的问题听起来像是有一个图表,PORT
是节点,LINK
是边。您的要求是,当您删除边缘时,边缘连接的两个节点也应该被删除。这可以通过覆盖节点的__del__
方法显式完成,以便删除它删除连接的边。
Python抽象出&#34;内存&#34;并且使用id
为您提供内存位置(这实际上是CPython的实现细节)的事实是一种执行此操作的简单方法。