从 b.diagonal() 获得的 Python ndarray a 在 b 修改后其值发生了变化

问题描述 投票:0回答:1

我对下面代码的行为有点困惑,想知道是否有人可以解释这一点。基本上我有一个名为 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]

diag 的值因 mat 的变化而变化

[100 100 100]

diag 的第一个值

100

及其地址

139863357577488

mat 的第一个值

100

及其地址

139863376059664

python python-3.x numpy numpy-ndarray
1个回答
0
投票

您无法通过

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
© www.soinside.com 2019 - 2024. All rights reserved.