解释器环境中的python垃圾收集和uuu下划线
如果在解释器环境中定义了类:解释器环境中的python垃圾收集和uuu下划线,python,garbage-collection,Python,Garbage Collection,如果在解释器环境中定义了类: class C(object): def __init__(self, val): self.x = val 然后不使用名称进行实例化: >>> C(1) >>> C(2) >>> 然后我们可以用下划线来指代C(2),所以我的问题是: 既然下划线“u”指的是C(2),我们可以说是参考吗 C(2)的计数器仍然是1?因此python gc将不释放 C(2) 据我所知,在这些C(2)被执
class C(object):
def __init__(self, val):
self.x = val
然后不使用名称进行实例化:
>>> C(1)
>>> C(2)
>>>
然后我们可以用下划线来指代C(2)
,所以我的问题是:
- 既然下划线“u”指的是
,我们可以说是参考吗C(2)
的计数器仍然是1?因此python gc将不释放C(2)
C(2)
- 据我所知,在这些
被执行之后,没有名字会引用C(2)
,所以我可以说一旦C(1)
被执行,C(2)
python gc是否将释放内存C(1)
>>> C(1) # Press Enter Key and run
>>>
>>> At Here, what is the exact reference count for the previous anonymous object "C(1)"?
>>> And how to prove?
>>>
>>> C(2) # Press Enter Key and run
>>>
>>> At Here, what is the exact reference count for the previous anonymous object "C(1)"?
>>> And how to prove?
代码> C(1)<代码>或<代码> C(2)最后一行解释时,它们在中间或代码中的行为不同。
如果C(1)
位于最后一行,python解释器将把它存储为
,因此实际上它将附加一个名称。如果选中实例数(C),结果将为1
如果C(1)
不在最后一行,则该临时匿名对象将被销毁并消失
检查以下测试代码
您可以使用numberofinstances
来显示内存中是否存在C
对象
import gc
def name_of_instances(cls):
return [obj for obj in gc.get_objects() if isinstance(obj, cls)]
def number_of_instances(cls):
return len([obj for obj in gc.get_objects() if isinstance(obj, cls)])
1.匿名对象不在最后一行
In [12]: C(1)
...: C(2)
...: print(number_of_instances(C))
...:
0
In [13]:
In [6]: C(1)
Out[6]: <__main__.C at 0x6a97ba8>
In [7]: print(number_of_instances(C))
...: print(name_of_instances(C))
...:
1
[<__main__.C object at 0x0000000006A97BA8>]
In [8]: C(2)
Out[8]: <__main__.C at 0x6a9b518>
In [9]: print(number_of_instances(C))
...: print(name_of_instances(C))
...:
2
[<__main__.C object at 0x0000000006A97BA8>, <__main__.C object at 0x0000000006A9B518>]
In [13]: C(3)
Out[13]: <__main__.C at 0x6aa06d8>
In [14]: type(_)
Out[14]: __main__.C
2.最后一行的匿名对象
In [12]: C(1)
...: C(2)
...: print(number_of_instances(C))
...:
0
In [13]:
In [6]: C(1)
Out[6]: <__main__.C at 0x6a97ba8>
In [7]: print(number_of_instances(C))
...: print(name_of_instances(C))
...:
1
[<__main__.C object at 0x0000000006A97BA8>]
In [8]: C(2)
Out[8]: <__main__.C at 0x6a9b518>
In [9]: print(number_of_instances(C))
...: print(name_of_instances(C))
...:
2
[<__main__.C object at 0x0000000006A97BA8>, <__main__.C object at 0x0000000006A9B518>]
In [13]: C(3)
Out[13]: <__main__.C at 0x6aa06d8>
In [14]: type(_)
Out[14]: __main__.C
但在这种情况下,引用计数器从不计算\uuu
中的引用,它只计算您未观察到的
这里有一个猜测:\uu
不在gc.garbage
列表中。如果连续运行C(1)
,print(实例数(C))
,number\u\u\u实例
将不会签入\u
,这可能存储了以前的C(1)
请看:@allen,非常感谢您的回答 根据您的猜测,我编写了以下代码:
In [3]: {'a': 1}
Out[3]: {'a': 1}
In [4]: C(1)
...: print(_)
...: print(type(_))
...: print(number_of_instances(C))
...:
{'a': 1}
<class 'dict'>
0
In [5]:
[3]中的:{'a':1}
Out[3]:{'a':1}
In[4]:C(1)
…:打印()
…:打印(类型())
…:打印(实例的数量(C))
...:
{'a':1}
0
在[5]中:
因此uu下划线仅用于存储“单步模式”解释器中最后一个表达式的值,而不用于“连续模式”
这可能是初学者经常犯的错误
无论如何,非常感谢你的回答 是的,基本上是这样。您可以使用
sys.getrefcount
@juanpa.arrivillaga从经验上探索这一点。如果我再次运行sys.getrefcount(C(2)),我预计结果将是2,因为最后一个下划线引用了它。但结果是1。因此,我认为您的解释不够令人信服。sys.getrefcount(C(2))
创建一个全新的C
对象,将其传递给refcount,并且从不将其绑定到名称。从来没有超过一个。.@juanpa.arrivillaga除了使用下划线外,我如何确保C(2)仍然存在于内存中?我的意思是,有没有办法检查最后一个C(2)是否仍然保留一个refcount?@juanpa.arrivillaga我想我没有解释清楚我的问题。我修改了我的问题使它更清楚。谢谢!我有一个相关的问题,也许你会知道答案