python垃圾收集和解释器环境中的_下划线

时间:2017-11-07 05:34:35

标签: python garbage-collection

如果在解释器环境中定义了类:

class C(object):
    def __init__(self, val):
        self.x = val

然后实例化没有名字:

>>> C(1)
>>> C(2)
>>> 

然后我们可以使用下划线_来引用C(2),所以这是我的问题:

  • 由于下划线' _'参考C(2),我们可以说参考 C(2)的计数器仍为1 ?所以python gc将不自由 C(2)
  • 占用的内存
  • 据我所知,执行这些C(2)后,没有名称会引用C(1),所以我可以说 C(2)执行,C(1)' s 内存将被python gc
  • 释放

这些实际上是4个问题,一个粗体字体。

gc:垃圾收集的简称

修改

让我通过直接评论代码来更清楚地说明我的第一个问题。

>>> 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?

2 个答案:

答案 0 :(得分:1)

C(1)C(2)作为解释器的最后一行,当它们位于代码的中间或上方时,行为会有所不同。

如果C(1)位于最后一行,python解释器会将其存储为<__main__.C object at 0x00000000********>,所以实际上它会附加一个名称。如果选中number_of_instances(C),结果将为1。

如果C(1)不在最后一行,则此临时匿名对象将被销毁并消失。

检查以下测试代码。

您可以使用number_of_instances来显示内存中是否有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]:

2.最后一行的匿名对象

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>]

3.underscore _会记住C(3),如果它是最后一行

In [13]: C(3)
Out[13]: <__main__.C at 0x6aa06d8>

In [14]: type(_)
Out[14]: __main__.C

但在这种情况下,引用计数器永远不会计算_的引用,它只会计算您未观察到的<__main__.C object at 0x0000000006AA06D8>

猜测:_不在gc.garbage列表中。如果您依次运行C(1)print(number_of_instances(C)),则number_of_instances将不会检入可能存储先前_的{​​{1}}

请参阅:sys.getrefcount continuation

答案 1 :(得分:0)

@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]:

因此_下划线仅用于存储“单步模式”的解释器中的最后一个表达式的值,而不是用于“连续模式”

这可能是初学者常犯的错误。

无论如何,非常感谢你的回答!