环境:Python 3.6.0 | Anaconda自定义(64位),numpy版本:1.11.3
例:
In[1]: import numpy as np
In[2]: a = np.array([[1,2,3], [4,5,6]])
In[3]: a
Out[4]:
array([[1, 2, 3],
[4, 5, 6]])
In[5]: a.transpose()[0] = -1
In[6]: a
Out[6]:
array([[-1, 2, 3],
[-1, 5, 6]])
In[7]: a.ravel()[0] = -2
In[8]: a
Out[8]:
array([[-2, 2, 3],
[-1, 5, 6]])
In[9]: a.transpose().ravel()[0] = -3
In[10]: a
Out[10]:
array([[-2, 2, 3],
[-1, 5, 6]])
我知道
transpose()
和ravel()
返回数组的视图,因此我们可以更改其原始数组的值。但是,当我们使用transpose().ravel()
时,我们不能更改它吗?为什么? 最佳答案
ravel
返回一个副本,而不是一个视图
从numpy.ravel
docs:
返回包含输入元素的一维数组。仅在需要时才进行复制。
因此,基本上,当破坏移调时,实际上需要一个副本。您正在更改副本中的值,因此不会反映在原始数组中。
测试返回的数组是视图还是副本
对于像这样的简单情况,可以通过比较b
和a
的标识来测试数组b.base
是否是a
的视图:
a = np.array([[1,2,3], [4,5,6]])
b = a.T
c = b.ravel()
print('b is a view of a\n%s\n' % (b.base is a))
print('c is a view of a\n%s\n' % (c.base is a))
输出:
b is a view of a
True
c is a view of a
False
为什么
a.T.ravel()
返回一个副本?Shocker:实际上,有一种方法可以使
a.T.ravel()
返回视图而不是副本。您可以通过显式设置order='F'
(即Fortran顺序)来实现:a = np.array([[1,2,3], [4,5,6]])
c = a.T.ravel()
d = a.T.ravel(order='F')
print('d is a view of a\n%s\n' % (d.base is a))
输出:
d is a view of a
True
但是,更改
order
kwarg的值将更改raveled数组中的值的顺序(即该值):print('c\n%s\n' % c)
print('d\n%s\n' % d)
输出:
c
[1 4 2 5 3 6]
d
[1 2 3 4 5 6]
为了理解为什么
order
的更改导致返回视图,我们可以查看ravel
函数本身的代码。 np.ndarray.ravel
的实现是buried in the C layer。通读源代码,很明显,为了从ravel
返回视图,必须满足两个条件:输入数组必须是连续的。
连续输入数组的顺序必须与传递到
order
的ravel
kwarg的顺序匹配。kwarg的默认值为
order='C'
。因此,默认情况下,如果在C连续数组上运行ravel
,则仅返回视图。在大多数情况下,初始化新的Numpy数组a
时,它会以C连续的形式开始。但是,转置a.T
将是F连续的。您可以通过检查数组的.flags
property在代码中看到这一点:a = np.array([[1,2,3], [4,5,6]])
print('the flags of a\n%s\n' % a.flags)
print('the flags of a.T\n%s\n' % a.T.flags)
输出:
the flags of a
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
the flags of a.T
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
C和F连续到底意味着什么?
对于您来说,C连续和F连续这两个词很有可能看起来像胡言乱语。对它们进行解释将需要另外一个完整的问题,很高兴SO上的某个人已经提出过。 a link to an old answer给出了C和F顺序实际含义的非常直观的概述。
警告
在您的实际代码中,我不必担心
ravel
是返回视图还是副本。实际上,通过确保使用视图并不能始终提高性能。通常应避免过早优化。关于python - a.transpose()。ravel()[0] = x无法更改numpy中原始数组的值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54166169/