【问题标题】:Python reference count to object fieldPython对对象字段的引用计数
【发布时间】:2020-03-17 22:22:20
【问题描述】:

以下代码在Python3的Mac终端上运行:

import gc

import numpy as np

class D(object):

    def __init__(self):
        self.value = np.arange(3)

    def get(self):
        return self.value


d = D()
print(gc.get_referrers(d))
print(type(gc.get_referrers(d)))
print()
print(len(gc.get_referrers(d)))
print(len(gc.get_referrers(d.value)))
print()

l = []
l.append(d)
print(len(gc.get_referrers(d)))
print(len(gc.get_referrers(d.value)))
print()

x = d.value
print(len(gc.get_referrers(d)))
print(len(gc.get_referrers(d.value)))

上面的代码会返回:

[{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10de6cef0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'test3.py', '__cached__': None, 'gc': <module 'gc' (built-in)>, 'np': <module 'numpy' from '/Users/jkim/Codes/Codes/Notebooks/venv3/lib/python3.6/site-packages/numpy/__init__.py'>, 'D': <class '__main__.D'>, 'd': <__main__.D object at 0x10dec7fd0>}]
<class 'list'>

1
0

2
0

2
1

谁能给我解释一下:

  1. 为什么对d.value0的引用计数,如果对d.value的引用计数确实是0,为什么d.value没有被Python收集垃圾?

  2. 引用对象d 的确切列表是什么?

谢谢!

【问题讨论】:

  • 你为什么要继承object?这是 Python 2 吗?如果是这样,请标记它。
  • 这是python3。我这样做是出于习惯。感谢您的编辑

标签: python garbage-collection


【解决方案1】:
  1. 引用计数不是 0。在 CPython 中您无法观察到引用计数为 0 的对象;您需要对对象的引用才能对其进行任何操作,并且该引用将计入其引用计数。您看到的是该对象没有 GC 跟踪的引荐来源网址。如果您想要实际的引用计数,请使用sys.getrefcount
  2. 没有引用该对象的列表。您正在采用gc.get_referrers 返回的推荐人列表的类型。此列表本身不是对象的引用者。

d.value 没有 GC 跟踪的引荐来源网址,原因如下。首先,d.value 是一个 NumPy 数组,其 dtype 不能保存对象引用,因此它不能参与引用循环。 NumPy 实现通过使它们不被 GC 跟踪来优化这些数组。

其次,对d.value的唯一引用是d.__dict__中的一个引用,以及访问d.value或将其传递给gc.get_referrers时创建的临时引用。临时引用位于当前堆栈帧的字节码操作数堆栈或 C 局部变量中,这些位置对 GC 不可见。 d.__dict__ 只持有无法被 GC 跟踪的对象(数组和 'value' 字符串),并且 CPython dict 实现不会 GC 跟踪 dict,直到插入能够被 GC 的键或值-tracked(或者在某些情况下,将 dict 创建为跟踪 dict 的副本)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-23
    • 2017-12-04
    • 1970-01-01
    • 2023-03-10
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    相关资源
    最近更新 更多