我对下面代码的行为有点困惑,想知道是否有人可以解释这一点。基本上我有一个名为 mat 的矩阵,它是一个 numpy ndarray,我使用 mat.diagonal() 获取它的对角线并将其分配给变量 diag 。我将 mat 的所有对角线值更改为 100,现在我发现 diag 的值也全部更改为 100,这似乎表明 diag 直接引用 mat 中的元素,但是当我抽查 diag 中第一个元素的内存地址时,与垫子相比,它们是不同的。怎样看待这个问题才是正确的呢?谢谢!
import numpy as np
import pandas as pd
mat_df = pd.DataFrame(data=[[1,2,3], [4,5,6], [7,8,9]])
print(mat_df)
mat = mat_df.values
diag = mat.diagonal()
print(diag)
diag_loc = np.diag_indices_from(mat)
mat[diag_loc] = 100
print(diag)
print(diag[0])
print(id(diag[0]))
print(mat[0][0])
print(id(mat[0][0]))
输出:
0 1 2 0 1 2 3 1 4 5 6 2 7 8 9
[1 5 9]
[100 100 100]
100
139863357577488
100
139863376059664
您无法通过
id
知道地址。首先, id
不返回地址(尽管如此,CPython 实现使用内存地址来构建 id
,这只是一种实现,并且本身不是地址)。其次,这只是 python 对象的地址(在您的情况下是包装 numpy.int64
的地址)。
该 python 对象只是为了包装任何 numpy 函数(对 python 不透明:python 不知道它们何时应该返回相同的值)返回而构建。
您可以做一些简单的实验来说服自己,您的
id
毫无意义
id(diag[0])
# 139729998312368
id(diag[0])
# 139730045496016
看,即使是连续两次完全相同的调用也不会返回相同的 id!
diag[0]
是对 numpy 的 diag.__getitem__(0)
的调用。包装到每次都不同的 python 容器中,就像调用任何函数 f(0)
的结果一样,没有理由假设每个相同的调用都会返回完全相同的结果。
因此,如果你想知道实际的
int64
存储在哪里,你不能问 python(及其 id
函数),因为这不仅是现在 id
的用途,而且更重要的是,python 不这样做我不知道。 int64
存储在哪里是 numpy 库的内部问题。所以你需要问numpy。
最好的方法是使用
base
恕我直言。
diag.base
#array([[100, 2, 3],
# [ 4, 100, 6],
# [ 7, 8, 100]])
但是,如果您坚持拥有某种地址,您也可以
diag.ctypes.data
# 61579664
mat.ctypes.data
# 61579664