为什么具名元组在 Python GC 中总会被跟踪?

在 Python 中,简单的元组如果仅包含不可变值,比如字符串、整数或另一个元组,则这些元组不会被 Python 的垃圾收集器 (GC) 跟踪。一旦 GC 确定这些简单的元组不会参与引用循环,就会将它们从跟踪中移除。让我们来看个例子:

import gc

x = (1, 2)
gc.is_tracked(x)  # True
gc.collect()
gc.is_tracked(x)  # False

然而,对于具名元组 (namedtuple) 则不同。尽管具名元组是元组的一个子类,但它们在 Python GC 中总是会被跟踪。即使具名元组仅包含不可变值,GC 也不会将它们从跟踪中移除。

import gc
from collections import namedtuple

foo = namedtuple('foo', ['x', 'y'])
x = foo(1, 2)
gc.is_tracked(x)  # True
gc.collect()
gc.is_tracked(x)  # True

2、解决方案

对于这个问题,目前还没有一个明确的答案。在 Python 源代码的 gcmodule.c 文件中,有一个注释解释了追踪和取消追踪的策略,但没有提到具名元组:

/* NOTE: about untracking of mutable objects.
         Certain types of container cannot participate in a reference cycle, and    so do not need to be tracked by the garbage collector.
  Untracking these    objects reduces the cost of garbage collections.
  However, determining    which objects may be untracked is not free,
  and the costs must be    weighed against the benefits for garbage
  collection.
There are two possible strategies for when to untrack a container:

When the container is created.   
When the container is examined by the garbage collector.

Tuples containing only immutable objects (integers, strings etc,
  and    recursively, tuples of immutable objects) do not need to be
  tracked.    The interpreter creates a large number of tuples, many of
  which will    not survive until garbage collection. It is therefore
  not worthwhile    to untrack eligible tuples at creation time.
Instead, all tuples except the empty tuple are tracked when
  created.     During garbage collection it is determined whether any
  surviving tuples     can be untracked. A tuple can be untracked if all
  of its contents are     already not tracked. Tuples are examined for
  untracking in all garbage     collection cycles. It may take more than
  one cycle to untrack a tuple.
Dictionaries containing only immutable objects also do not need to
  be    tracked. Dictionaries are untracked when created. If a tracked
  item is    inserted into a dictionary (either as a key or value), the
  dictionary    becomes tracked. During a full garbage collection (all
  generations),    the collector will untrack any dictionaries whose
  contents are not    tracked.
The module provides the python function is_tracked(obj), which
  returns    the current tracking status of the object. Subsequent
  garbage    collections may change the tracking status of the object.
  Untracking of certain containers was introduced in issue #4688, and     the algorithm was refined in response to issue #14775.
*/

在 Python 中,具名元组是一种容器类型,它与字典类似,可以给每个值赋予一个名字。具名元组可以被继承,这意味着可以创建具名元组的子类。这些子类可能不是不可变的,因此 GC 无法确定它们是否可以从跟踪中移除。为了确保 GC 能够正确地跟踪具名元组,Python 解释器会在创建具名元组时将其标记为已跟踪。

因此,具名元组总是会被 Python 的 GC 跟踪。虽然这可能会导致一些性能下降,但它可以确保 GC 能够正确地管理具名元组的内存。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值