在麻木中,平展函数和拉开函数的区别是什么?

import numpy as np
y = np.array(((1,2,3),(4,5,6),(7,8,9)))
OUTPUT:
print(y.flatten())
[1   2   3   4   5   6   7   8   9]
print(y.ravel())
[1   2   3   4   5   6   7   8   9]

两个函数返回相同的列表。 那么为什么需要两个不同的函数执行同样的工作。

114571 次浏览

当前的API是:

  • flatten总是返回一个副本。
  • ravel尽可能返回原始数组的视图。这在打印输出中是不可见的,但是如果修改了ravel返回的数组,它可能会修改原始数组中的条目。如果你修改flatten返回的数组中的条目,这将永远不会发生。由于没有复制内存,Ravel通常会更快,但在修改它返回的数组时必须更加小心。
  • reshape((-1,))在数组的步长允许的情况下获得一个视图,即使这意味着你并不总是得到一个连续的数组。

正如在这里所解释的,一个关键的区别是:

  • flatten是ndarray对象的方法,因此只能用于真正的numpy数组。

  • ravel是一个库级函数,因此可以在任何可以成功解析的对象上调用。

例如,ravel可以用于ndarray列表,而flatten则不能用于该类型的对象。

@IanH在他的回答中也指出了内存处理的重要区别。

下面是函数的正确命名空间:

这两个函数都返回指向新内存结构的扁平1D数组。

import numpy
a = numpy.array([[1,2],[3,4]])


r = numpy.ravel(a)
f = numpy.ndarray.flatten(a)


print(id(a))
print(id(r))
print(id(f))


print(r)
print(f)


print("\nbase r:", r.base)
print("\nbase f:", f.base)


---returns---
140541099429760
140541099471056
140541099473216


[1 2 3 4]
[1 2 3 4]


base r: [[1 2]
[3 4]]


base f: None

在上面的例子中:

  • 结果的记忆位置是不同的,
  • 结果看起来是一样的
  • Flatten将返回一个副本
  • 拉威尔将返回一个视图。

我们如何检查某些东西是否是副本? 使用ndarray. properties的.base属性。如果它是一个视图,基将是原始数组;如果它是一个副本,则基数将是None.


检查a2是否是a1的副本

import numpy
a1 = numpy.array([[1,2],[3,4]])
a2 = a1.copy()
id(a2.base), id(a1.base)

:

(140735713795296, 140735713795296)