对不存在的数组使用 numpy 视图

Posted

技术标签:

【中文标题】对不存在的数组使用 numpy 视图【英文标题】:Using a numpy view to a non-existing array 【发布时间】:2018-01-25 14:45:32 【问题描述】:

在定义一个带零的数组a 后,我可以使用以下函数创建一个最左侧列的视图:

a = np.zeros((5, 5))
a_left_col = a[:, 0]

a_left_col[:] = 2.

a打印:

array([[2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.]])

如果我随后用

重新初始化a
a = np.zeros((5, 5))

那么视图仍然存在,但它不再引用任何内容。如果我再次a_left_col[:] = 2,Python 将如何处理这种情况?这是像 C 或 C++ 中的未定义行为,还是 Python 能正确处理它,如果是,为什么不抛出错误?

【问题讨论】:

引用计数。原始对象a 仍然存在,因为它被视图引用。 (虽然不能再通过变量a访问。) 【参考方案1】:

原始对象仍然存在,因为它被视图引用。 (虽然不能再通过变量a访问。)

让我们详细看看对象的引用计数:

import sys
import numpy as np

a = np.zeros((5, 5))
print(sys.getrefcount(a))  # 2

a_left_col = a[:, 0]
print(sys.getrefcount(a))  # 3
print(sys.getrefcount(a_left_col.base))  # 3
print(a_left_col.base is a)  # True

a = np.ones((5, 5))
print(sys.getrefcount(a_left_col.base))  # 2

请注意,a_left_col.base 是对原始数组的引用。当我们重新评估a 时,对象上的引用计数会减少,但它仍然存在,因为它可以通过a_left_col 访问。

【讨论】:

有趣。那么在视图的情况下,我必须自己做内存管理? @Chiel 不,这都是自动的。虽然存在数组中的视图,但它们算作对对象的引用。当一个对象不再被引用(不再有视图或其他引用)时,它会在某个时候被垃圾收集器删除。 我明白了,但是由于我倾向于为快捷方式创建很多视图,这意味着我必须明确删除所有视图,以便恢复记忆。对吗? @Chiel 没错。但是,这通常只是变量存在的长脚本中的问题。当函数返回时,所有作为局部变量存在的视图都将被删除;如果您重新分配一个变量(例如,在循环中),您也不必显式删除它。【参考方案2】:

行为不是未定义的。您只是在创建一个新对象a。旧的没有被释放,但仍然存在于内存中,因为 a_left_col 仍然引用它。一旦你重新初始化a_left_col,原始数组就可以被释放了。

【讨论】:

以上是关于对不存在的数组使用 numpy 视图的主要内容,如果未能解决你的问题,请参考以下文章

诚之和:Numpy怎么检查数组全为零的几种方法

destoon对不起,您查找的页面不存在,以下信息有没有您需要的?

正确响应 PROPFIND 对不存在的资源的响应

使用 Nginx 使用 try_files 将所有对不存在文件的请求重写为 index.php

SELECT … FOR UPDATE 对不存在的行

如何在django admin中对不存在的字段进行排序/排序[重复]