Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python a、 transpose().ravel()[0]=x无法更改numpy中原始数组的值?_Python_Numpy_Deep Copy - Fatal编程技术网

Python a、 transpose().ravel()[0]=x无法更改numpy中原始数组的值?

Python a、 transpose().ravel()[0]=x无法更改numpy中原始数组的值?,python,numpy,deep-copy,Python,Numpy,Deep Copy,环境:Python 3.6.0 | Anaconda定制(64位),numpy版本:1.11.3 例如: 我知道transpose()和ravel()返回数组的视图,因此我们可以更改其原始数组的值。但是,当我们使用transpose().ravel()时,我们不能更改它吗?为什么? ravel正在返回副本,而不是视图 从: 返回一个包含输入元素的一维数组。只有在需要时才制作副本 因此,基本上,当解开转置时,实际上需要一个副本。您正在更改副本中的值,因此该值不会反映在原始数组中 测试返回的数组是视

环境:Python 3.6.0 | Anaconda定制(64位),numpy版本:1.11.3
例如:

我知道
transpose()
ravel()
返回数组的视图,因此我们可以更改其原始数组的值。但是,当我们使用
transpose().ravel()
时,我们不能更改它吗?为什么?

ravel
正在返回副本,而不是视图 从:

返回一个包含输入元素的一维数组。只有在需要时才制作副本

因此,基本上,当解开转置时,实际上需要一个副本。您正在更改副本中的值,因此该值不会反映在原始数组中

测试返回的数组是视图还是副本 对于这种简单的情况,您可以通过比较
b.base
a
的标识来测试数组
b
是否是
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
d is a view of a
True
c
[1 4 2 5 3 6]

d
[1 2 3 4 5 6]
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
为什么
a.T.ravel()
会返回副本? 令人震惊的是:实际上有一种方法可以使
a.T.ravel()
返回视图而不是副本。您可以通过显式设置
order='F'
(即Fortran顺序)来执行此操作:

输出:

b is a view of a
True

c is a view of a
False
d is a view of a
True
c
[1 4 2 5 3 6]

d
[1 2 3 4 5 6]
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
但是,更改
order
kwarg的值将更改raveled数组中值的顺序(想象一下):

print('c\n%s\n' % c)
print('d\n%s\n' % d)
输出:

b is a view of a
True

c is a view of a
False
d is a view of a
True
c
[1 4 2 5 3 6]

d
[1 2 3 4 5 6]
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
为了理解为什么
顺序的更改会导致返回视图,我们可以查看
ravel
函数本身的代码。
np.ndarray.ravel
的实现是。从源代码中可以看出,要从
ravel
返回视图,必须满足两个条件:

  • 输入数组必须是连续的

  • 连续输入数组的顺序必须与传递到
    ravel
    顺序
    kwarg的顺序匹配

kwarg的默认值为
order='C'
。因此,默认情况下,
ravel
仅在C连续数组上运行视图时才会返回视图。大多数情况下,当您初始化一个新的Numpy数组
a
时,它将以C-连续开始。然而,转置
a.T
将是F-连续的。通过检查数组的名称,您可以在代码中看到这一点:

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)
输出:

b is a view of a
True

c is a view of a
False
d is a view of a
True
c
[1 4 2 5 3 6]

d
[1 2 3 4 5 6]
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-连续这两个术语对您来说似乎是胡言乱语。解释它们需要一个完全不同的问题,很高兴有人已经问过了。这是一个非常直观的概述,说明了C和F顺序的实际含义

警告 在实际代码中,我不会太担心
ravel
是返回视图还是副本。实际上,通过确保视图的使用,您并不总能获得性能提升。通常避免过早优化

In [382]: a = np.array([[1,2,3], [4,5,6]])
In [383]: a
Out[383]: 
array([[1, 2, 3],
       [4, 5, 6]])
In [384]: a.ravel()
Out[384]: array([1, 2, 3, 4, 5, 6])
ravel
给出数组的一维视图,并按值在数据缓冲区中出现的顺序显示值

In [385]: a.T
Out[385]: 
array([[1, 4],
       [2, 5],
       [3, 6]])
In [386]: a.T.ravel()
Out[386]: array([1, 4, 2, 5, 3, 6])
转置的
ravel
以不同的顺序显示元素-除非我们将顺序指定为“F”(或“K”)

ravel
(和其他操作)如果阵列可以使用原始数据,只需更改
形状和
跨步
,即可创建
视图。如果不能,它必须复制一份

由于使用转置对元素顺序进行了更改,因此使用
[0]
以外的内容进行索引时,会选择不同的值:

In [397]: a.ravel()[3]
Out[397]: 4               # -1 in your Out[8]
In [398]: a.T.ravel()[3]
Out[398]: 5

你看,当你要求改变转置的第四个元素时,会有一定的歧义。它可以根据您遍历元素的方式而有所不同。

为什么要拆转置,实际上需要一个副本?好的,我已经添加了所有关于为什么
ravel
返回一个副本而不是视图的详细信息。遗憾的是,这有点复杂(大约是我原来答案的3倍)。