【问题标题】:Unexpected result from sys.getrefcount来自 sys.getrefcount 的意外结果
【发布时间】:2009-04-17 09:29:39
【问题描述】:

当我输入时:

>>> astrd = 123
>>> import sys
>>> sys.getrefcount(astrd)
3
>>> 

我不知道astrd 在哪里使用了 3 次?

【问题讨论】:

    标签: python garbage-collection


    【解决方案1】:

    被引用三次的不是astrd,而是值123astrd 只是(不可变)数字 123 的名称,可以多次引用。除此之外,通常共享小整数:

    >>> astrd = 123
    >>> sys.getrefcount(astrd)
    4
    >>> j = 123
    >>> sys.getrefcount(astrd)
    5
    

    在第二个赋值中,没有创建新的整数,而是j 只是整数123 的新名称。

    但是,给定非常大的整数,这不成立:

    >>> i = 823423442583
    >>> sys.getrefcount(i)
    2
    >>> j = 823423442583
    >>> sys.getrefcount(i)
    2
    

    共享整数是 CPython(以及其他)的一个实现细节。由于小整数经常被实例化,共享它们可以节省大量内存。这是因为整数是不可变的。

    有关第二个示例中的附加参考,请参阅。 codeape's answer.

    【讨论】:

      【解决方案2】:

      来自getrefcount docstring

      ... 返回的计数通常比您预期的高 1, 因为它包含(临时)引用作为getrefcount() 的参数。

      另外两个引用意味着 python 在内部持有两个对该对象的引用。也许 locals() 和 globals() 字典都算作一个引用?

      【讨论】:

      • 所以当我执行“del astrd”时,它的引用计数变为 0 并被 gc 收集?
      【解决方案3】:

      我认为它计算了对 123 的引用,请尝试其他示例,例如

      >>> import sys
      >>> astrd = 1
      >>> sys.getrefcount(astrd)
      177
      >>> astrd = 9802374987193847
      >>> sys.getrefcount(astrd)
      2
      >>> 
      

      9802374987193847 的引用计数符合 codeape 的答案。

      这可能是因为数字是不可变的。例如,如果您使用一个列表,它将始终为 2(来自一个干净的提示)。

      顺便说一句,我也得到 123 的 2,也许你的设置有些不同?或者可能与时间有关?

      【讨论】:

        【解决方案4】:

        ints 以一种特殊的方式实现,它们被缓存和共享,这就是为什么你没有得到 1。

        和 python,使用引用计数的对象。 astrd 本身就是一个引用,因此您实际上获得了对 int '123' 的引用数。尝试使用另一种(用户定义的)类型,你会得到 1。

        【讨论】:

          猜你喜欢
          • 2014-04-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-27
          • 2015-11-02
          • 1970-01-01
          相关资源
          最近更新 更多