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]
这两个函数返回相同的列表。 那么为什么需要两个不同的函数执行同样的工作呢。
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]
这两个函数返回相同的列表。 那么为什么需要两个不同的函数执行同样的工作呢。
当前API的情况是:
flatten
总是返回一个副本。ravel
尽可能返回原始数组的视图。这在打印输出中不可见,但如果您修改ravel返回的数组,则可能会修改原始数组中的条目。如果您修改从flatten返回的数组中的条目,则永远不会发生这种情况。由于没有复制内存,因此ravel通常会更快,但您必须更加谨慎地修改它返回的数组。reshape((-1,))
如果数组的步幅允许,则获取视图,即使这意味着您不总是获得一个连续的数组。a.flatten()
以确保获得副本,a.ravel()
避免大多数复制但仍保证返回的数组是连续的,以及a.reshape((-1,))
真正获取视图只要数组的步幅允许即使这意味着您并不总是获得连续的数组。 - IanHravel
保证返回一个连续的数组,因此不能保证它返回的是视图;reshape
总是返回一个视图,因此不能保证它返回的是一个连续的数组。 - iled如这里所解释的关键区别在于:
flatten
是ndarray对象的一个方法,因此只能应用于真正的numpy数组。
ravel
是一个库级函数,因此可以应用于任何可以成功解析的对象。
例如,ravel
将在ndarrays列表上工作,而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
在上面的例子中:
ndarray
的.base
属性。如果它是一个视图,基础将是原始数组;如果它是副本,则基础将为None
。
a2
是否是a1
的副本。import numpy
a1 = numpy.array([[1,2],[3,4]])
a2 = a1.copy()
id(a2.base), id(a1.base)
输出:
(140735713795296, 140735713795296)
id(a1.base)
should be the same as id(a2.base)
- prosti