预备条件

您需要了解Python、如有必要,请参考Python tutorial复习下.

为了后续例子运行, 您需要在numpy之外安装’matplotlib'

目的简介

这里是Numpy中数组的快速概览。展示了n-维($n>=2$)数组的表示和操作方法。 特别的、如何不熟悉n维数组的的通用函数应用(不使用python的for循环),或者想进一步了解n维数组的axis和shape属性,本文应该有些帮助     学习目标

学习本文之后、您应该掌握:

  • 理解numpy中一维、二维和n-维数组的不同;
  • 理解如何在不使用for-循环时对n维数组应用一些线性代数操作;
  • 理解n维数组的维axis和形状shape属性.

基础概念

Numpy的主要对象是同构的多维数组。它是元素(通常是数字)的表、都是同一类型、以非零整数的元组为索引。 在Numpy中维被称为 axes(轴)

比如、在3D空间的一个点的坐标的的数组,[1, 2, 1], 具有一个轴。这个轴内有3个元素,我们称其长度为3. 在下面的例子中,数组具有2个轴。第一个轴具有长度2,第二个轴的长度为3.

1
2
    [[1., 0., 0.],
     [0., 1., 2.]]

NumPy的数组类称为 ndarray. 它还有另外一个别名array. 请注意 numpy.array 和Python标准库的类array.array不一样, 后者仅仅处理一维数组并且提供很少的共功能。

ndarray 对象的很重要的属性如下:

ndarray.ndim

轴(维度)的数量

ndarray.shape

维度的大小。数组在每个维度的数组大小的整数的元组。比如 n 行和 m 列的矩阵,其shape(n,m)shape元组的长度即是轴的数量 ndim

ndarray.size

数组中所有元素的数量, 和shape元组中元素乘积相等.

ndarray.dtype

数据类型、数组元素类型的描述对象。用户可以使用标准python类型创建或者声明数据类型。 另外Numpy提供了自己的一些类型。比如numpy.int32, numpy.int16, andnumpy.float64等

ndarray.itemsize

数组内每个元素所占字节大小。比如、 元素类型为float64的数组、其itemsize是8(=64/8), 而类型为 complex32 的数组、对应的itemsize 是 4 (=32/8)。这个属性和ndarray.dtype.itemsize属性相等.

ndarray.data

包含数组实际元素的内存缓冲区。一般情况下、我们不会使用这个属性,因为我们通过索引功能来访问数组包含的元素.

数组实例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> import numpy as np
>>> a = np.arange(15).reshape(3, 5)   #创建从0到15(不包含)的数组 #reshape 改变数组的shape
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int64'
>>> a.itemsize
8
>>> a.size
15
>>> type(a)
<type 'numpy.ndarray'>
>>> b = np.array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
<type 'numpy.ndarray'>

数组创建

创建numpy数组的方式有多种:

比如、可以使用常规的python列表或者元组应用 array 函数来创建数组。 生成的数组的类型从python序列的元素类型推断而来

>>> import numpy as np
>>> a = np.array([2, 3, 4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int64')
>>> b = np.array([1.2, 3.5, 5.1])
>>> b.dtype
dtype('float64')

一个常见错误是调用array函数时提供多个参数、 这里正确的做法应该是提供一个作为参数的python序列

>>> a = np.array(1, 2, 3, 4)    # WRONG **错误**
Traceback (most recent call last):
  ...
TypeError: array() takes from 1 to 2 positional arguments but 4 were given
>>> a = np.array([1, 2, 3, 4])  # RIGHT **正确**

array 函数将序列的序列转换成二维数组,将序列的序列的序列转换成三维数组,以此类推。

>>> b = np.array([(1.5, 2, 3), (4, 5, 6)])
>>> b
array([[1.5, 2. , 3. ],
       [4. , 5. , 6. ]])

也可以在创建数组时明确指定数组元素类型:

>>> c = np.array([[1, 2], [3, 4]], dtype=complex)
>>> c
array([[1.+0.j, 2.+0.j],
       [3.+0.j, 4.+0.j]])

通常、数组的元素最初是未知的,但是它的大小已知。因此,numpy提供了几个函数来创建以初始占位符为内容的数组。 这样最小化了对数组增长的需求,实际上数组增长是一个昂贵的操作。

函数zeros创建充满0的数组,函数 ones创建充满1的数组, 函数empty创建的数组依赖于内存状态、内容是随机的。默认情况下,创建的数组的dtype类型是 float64, 但是,也可以通过关键字参数 dtype来指定dtype.

>>> np.zeros((3, 4))
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
>>> np.ones((2, 3, 4), dtype=np.int16)
array([[[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]],
       [[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]]], dtype=int16)
>>> np.empty((2, 3))
array([[3.73603959e-262, 6.02658058e-154, 6.55490914e-260],  # 随机的数值
       [5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])

Numpy提供了函数 arange 来创建数字序列,它与python的内置函数range类似,但是返回的是数组

>>> np.arange(10, 30, 5)
array([10, 15, 20, 25])
>>> np.arange(0, 2, 0.3)  # 接受浮点数作为参数
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])

通常使用浮点数作为 arange 的参数,由于浮点数的有限精度的原因,不太可能预知获得的元素的数量。 由此,最好使用函数 linspace,它接受一个表示我们想获得的元素数量(而不是步长)的参数:

>>> from numpy import pi
>>> np.linspace(0, 2, 9)       # 获得从0到2的9个数字
array([0.  , 0.25, 0.5 , 0.75, 1.  , 1.25, 1.5 , 1.75, 2.  ])
>>> x = np.linspace(0, 2 * pi, 100)  # 在函数多点求值时很有用
>>> f = np.sin(x)

** 更多数组创建函数请参考NumPy数组创建函数 **

打印数组

打印数组时,Numpy展示其内容的方式与嵌套的python列表接近。不过,具有下面的布局特点:

  • 最后的轴从左到右打印 ,
  • 倒数第二个轴从上到下打印 ,
  • 其他轴也从上到下打印,每个切块同尾随的切块之间用空行分割.

一维数组打印成行,二维数组打印成矩阵,三维数组打印成矩阵列表

>>> a = np.arange(6)                    # 1d array
>>> print(a)
[0 1 2 3 4 5]
>>>
>>> b = np.arange(12).reshape(4, 3)     # 2d array
>>> print(b)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
>>>
>>> c = np.arange(24).reshape(2, 3, 4)  # 3d array
>>> print(c)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]
<BLANKLINE>
 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]

参考下面的 reshape获得 reshape函数的更多信息.

如果数组内容太多无法全部打印出来,那么Numpy自动省略数组的中间部分,仅仅打印角落。

>>> print(np.arange(10000))
[   0    1    2 ... 9997 9998 9999]
>>>
>>> print(np.arange(10000).reshape(100, 100))
[[   0    1    2 ...   97   98   99]
 [ 100  101  102 ...  197  198  199]
 [ 200  201  202 ...  297  298  299]
 ...
 [9700 9701 9702 ... 9797 9798 9799]
 [9800 9801 9802 ... 9897 9898 9899]
 [9900 9901 9902 ... 9997 9998 9999]]

如果想禁用打印省略功能,强制Numpy打印整个数组,可以设置参数 set_printoptions 来改变打印的设置.

>>> np.set_printoptions(threshold=sys.maxsize)  # 模块sys应该已导入

基础操作

数学符号按照 按元素展开 的方式应用在数组各个元素上,会创建一个新的数组并填入作为结果的内容。

>>> a = np.array([20, 30, 40, 50])
>>> b = np.arange(4)
>>> b
array([0, 1, 2, 3])
>>> c = a - b
>>> c
array([20, 29, 38, 47])
>>> b**2
array([0, 1, 4, 9])
>>> 10 * np.sin(a)
array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854])
>>> a < 35
array([ True,  True, False, False])

与其他矩阵语言不同,乘积符号 * 在Numpy数组中按元素展开进行操作。 矩阵乘积可以使用 @ 符号来完成(python>=3.5),也可以使用dot 函数或方法:

>>> A = np.array([[1, 1],
...               [0, 1]])
>>> B = np.array([[2, 0],
...               [3, 4]])
>>> A * B     # 按位展开的乘积
array([[2, 0],
       [0, 4]])
>>> A @ B     # 矩阵乘积
array([[5, 4],
       [3, 4]])
>>> A.dot(B)  # 另外一种矩阵乘积方式
array([[5, 4],
       [3, 4]])

一些运算比如 += and *=, 会操作修改现存数组而不是创建一个新数组。

>>> rg = np.random.default_rng(1)  # 创建默认随机数生成器的的实例
>>> a = np.ones((2, 3), dtype=int)
>>> b = rg.random((2, 3))
>>> a *= 3
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
>>> b += a
>>> b
array([[3.51182162, 3.9504637 , 3.14415961],
       [3.94864945, 3.31183145, 3.42332645]])
>>> a += b  # ** b不会自动转换为整数类型 **
Traceback (most recent call last):
    ...
numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

当操作不同类型数组时,计算结果的数组类型对应于输入数组中更一般或者说更精确的类型(称为向上数据类型转换).

>>> a = np.ones(3, dtype=np.int32)
>>> b = np.linspace(0, pi, 3)
>>> b.dtype.name
'float64'
>>> c = a + b
>>> c
array([1.        , 2.57079633, 4.14159265])
>>> c.dtype.name
'float64'
>>> d = np.exp(c * 1j)
>>> d
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
       -0.54030231-0.84147098j])
>>> d.dtype.name
'complex128'

许多一元运算,比如计算数组内所有元素的和,通过 ndarray 类的方法来实现

>>> a = rg.random((2, 3))
>>> a
array([[0.82770259, 0.40919914, 0.54959369],
       [0.02755911, 0.75351311, 0.53814331]])
>>> a.sum()
3.1057109529998157
>>> a.min()
0.027559113243068367
>>> a.max()
0.8277025938204418

默认情况下,这些操作应用于数组,操作方式就好像数字列表一样,和数组的shape形状无关。 不过,通过声明 axis 参数,可以沿着指定的轴展开运算:

>>> b = np.arange(12).reshape(3, 4)
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> b.sum(axis=0)     # 每列的和
array([12, 15, 18, 21])
>>>
>>> b.min(axis=1)     # 每行的最小值
array([0, 4, 8])
>>>
>>> b.cumsum(axis=1)  # 沿着行方向的累计和
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38]])

通用函数

Numpy提供了常见的数学函数,比如 sin、cos和exp。在Numpy中,这些函数被称为numpy的"universal functions" (ufunc)通用函数, 这些函数以遍历数组元素的方式的操作,生成新的数组作为输出。

>>> B = np.arange(3)
>>> B
array([0, 1, 2])
>>> np.exp(B)
array([1.        , 2.71828183, 7.3890561 ])
>>> np.sqrt(B)
array([0.        , 1.        , 1.41421356])
>>> C = np.array([2., -1., 4.])
>>> np.add(B, C)
array([2., 0., 6.])

** 更多基础函数通用函数例子请参考NumPy通用函数例子 **

索引、切片、和迭代

一维 数组可以索引、切片和迭代, 操作方式和 python 列表 以及其它python序列很相似.

>>> a = np.arange(10)**3   //立方
>>> a
array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729])
>>> a[2]
8
>>> a[2:5]
array([ 8, 27, 64])
>>> # 与 a[0:6:2] = 1000 等效;
>>> # 从开始到第六个(不包含)位置,设置每第二个元素为1000
>>> a[:6:2] = 1000
>>> a
array([1000,    1, 1000,   27, 1000,  125,  216,  343,  512,  729])
>>> a[::-1]  # 列表反转
array([ 729,  512,  343,  216,  125, 1000,   27, 1000,    1, 1000])
>>> for i in a:
...     print(i**(1 / 3.))   #立方根
...
9.999999999999998
1.0
9.999999999999998
3.0
9.999999999999998
4.999999999999999
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998

多维 数组可以每个轴拥有索引,这些索引以逗号分割的元组的形式展现:

>>> def f(x, y):
...     return 10 * x + y
...
>>> b = np.fromfunction(f, (5, 4), dtype=int)
>>> b
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])
>>> b[2, 3]
23
>>> b[0:5, 1]  # 每一行的第二列
array([ 1, 11, 21, 31, 41])
>>> b[:, 1]    # 同上
array([ 1, 11, 21, 31, 41])
>>> b[1:3, :]  # 第二和第三行的每列
array([[10, 11, 12, 13],
       [20, 21, 22, 23]])

当提供的索引数量少于轴数量时,缺失的索引当作全切片符号:处理

>>> b[-1]   # 最后一行,等价于 [-1, :]
array([40, 41, 42, 43])

b[i]中括号中的表达式被当作 i 后面跟随着很多::冒号的数量由表示剩下的轴的需要而定. Numpy中还允许使用句号.,b[i, ...]

这里句号 (...)表示构建完整索引元祖所需的那么多冒号。 假如 x 是一个具有5轴的数组,那么

  • x[1, 2, ...] 等价于 x[1, 2, :, :, :],
  • x[..., 3] 等于 x[:, :, :, :, 3] and
  • x[4, ..., 5, :] 等于 x[4, :, :, 5, :]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    >>> c = np.array([[[  0,  1,  2],  # 三维数组(二个堆砌的2维数组)
    ...                [ 10, 12, 13]],
    ...               [[100, 101, 102],
    ...                [110, 112, 113]]])
    >>> c.shape
    (2, 2, 3)

    >>> c[1, ...]  # 同 c[1, :, :] 或者 c[1]
    array([[100, 101, 102],
           [110, 112, 113]])

    >>> c[..., 2]  # 同 c[:, :, 2]
    array([[  2,  13],
           [102, 113]])

多维数组的迭代是相对于第一个轴而展开的:

>>> for row in b:
...     print(row)
...
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]

如果想对数组中每一个元素进行某个操作,可以使用数组的flat属性,这是一个遍历数组所有元素的iterator:

>>> for element in b.flat:
...     print(element)
...
0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33
40
41
42
43

** 更多Numpy索引例子请参考NumPy索引例子 **

形状操作

改变数组的形状

数组的形状属性由数组沿每个轴的元素数量定义:

>>> a = np.floor(10 * rg.random((3, 4)))
>>> a
array([[3., 7., 3., 4.],      # 3行4列
       [1., 4., 2., 2.],
       [7., 2., 4., 9.]])
>>> a.shape
(3, 4)

可以通过许多命令改变数组的形状。请注意下面的三个命令都会返回修改的数组、并不会改变原数组:

>>> a.ravel()  # 返回扁平化flattened的数组
array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.])
>>> a.reshape(6, 2)  # 返回形状改变的数组
array([[3., 7.],
       [3., 4.],
       [1., 4.],
       [2., 2.],
       [7., 2.],
       [4., 9.]])
>>> a.T  # 返回转置的数组
array([[3., 1., 7.],
       [7., 4., 2.],
       [3., 2., 4.],
       [4., 2., 9.]])
>>> a.T.shape
(4, 3)
>>> a.shape
(3, 4)

数组 ravel操作的返回ß结果数组中元素的顺序一般符合"C-style"C语言样式, 也就是说,最右边的索引“变化的最快”,因此在元素 a[0, 0] 之后是 a[0, 1]。 如果数组重新改变形状成其他形状,结果数组同样具有C语言样式。 通常Numpy创建的数组的数据存储就符合这样顺序,因此ravel通常并不需要copy它的参数数据, 不过如果数组由其他数组切片或者通过不常见的选项构建,那么可能就需要copy它的参数数据。 函数 ravelreshape 可以使用可选参数来定制使用FORTRAN样式的数组, FORTRAN数组中变化最快的是左边索引。

reshape函数返回数组改变的形状,而[ndarray.resize]{.title-ref}方法修改数组本身:

>>> a
array([[3., 7., 3., 4.],
       [1., 4., 2., 2.],
       [7., 2., 4., 9.]])
>>> a.resize((2, 6))
>>> a
array([[3., 7., 3., 4., 1., 4.],
       [2., 2., 7., 2., 4., 9.]])

If a dimension is given as -1 in a reshaping operation, the other dimensions are automatically calculated: 如果reshape操作的形状参数中一个是 -1 ,那么这个参数会自动(根据数组长度和其他形状参数)被计算出来:

>>> a.reshape(3, -1)
array([[3., 7., 3., 4.],
       [1., 4., 2., 2.],
       [7., 2., 4., 9.]])

** 更多Numpy形状修改例子请参考NumPy形状修改例子 **

堆砌不同数组

几个数组可以沿不同的轴堆砌起来:

>>> a = np.floor(10 * rg.random((2, 2)))
>>> a
array([[9., 7.],
       [5., 2.]])
>>> b = np.floor(10 * rg.random((2, 2)))
>>> b
array([[1., 9.],
       [5., 1.]])
>>> np.vstack((a, b))   #vstack vertical 垂直堆砌
array([[9., 7.],
       [5., 2.],
       [1., 9.],
       [5., 1.]])
>>> np.hstack((a, b))   #hstack horizontal 水平堆砌
array([[9., 7., 1., 9.],
       [5., 2., 5., 1.]])

将一维数组作为数据列,进而堆砌成二维数组。 仅仅对于二维数组而言它和[hstack]{.title-ref}等效。

>>> from numpy import newaxis
>>> np.column_stack((a, b))  # with 2D arrays
array([[9., 7., 1., 9.],
       [5., 2., 5., 1.]])
>>> a = np.array([4., 2.])
>>> b = np.array([3., 8.])
>>> np.column_stack((a, b))  # returns a 2D array
array([[4., 3.],
       [2., 8.]])
>>> np.hstack((a, b))        # the result is different
array([4., 2., 3., 8.])
>>> a[:, newaxis]  # view `a` as a 2D column vector
array([[4.],
       [2.]])
>>> np.column_stack((a[:, newaxis], b[:, newaxis]))
array([[4., 3.],
       [2., 8.]])
>>> np.hstack((a[:, newaxis], b[:, newaxis]))  # the result is the same
array([[4., 3.],
       [2., 8.]])

相反,函数[row_stack]{.title-ref}对于任何输入数组等价于[vstack]{.title-ref}。 实际上,[row_stack]{.title-ref} 是 vstack的别名: »> np.column_stack is np.hstack False »> np.row_stack is np.vstack True

一般来说,对于多于二维的数组 函数[hstack]{.title-ref} 沿着他们的第二个轴堆砌, 函数[vstack]{.title-ref} 沿着他们的第一个轴堆砌, 函数[concatenate]{.title-ref} 接受一个可选参数, 这个参数提供了几个轴,沿着这些轴展开连接数组操作

注意

对于一些复杂的用例,需要沿着轴堆砌数字时,函数[r_]{.title-ref} 和 [c_]{.title-ref}很有用。 它们接受使用冒号:的区间范围字符串作为参数:

>>> np.r_[1:4, 0, 4]
array([1, 2, 3, 0, 4])

当使用数组参数时,[r_]{.title-ref} 和 [c_]{.title-ref} 的缺省行为与 [vstack]{.title-ref} 和[hstack]{.title-ref}相似,不过它们还可以接受一个可选参数, 给出连接操作的轴的数。

** 更多Numpy堆砌例子请参考NumPy堆砌例子 **

将数组分成小数组

使用[hsplit]{.title-ref}函数,可以将数组沿着水平轴分割, 指定返回的相同形状的小数组的数量,或者声明数据列,指定在其后发生数组分割的数据列。

>>> a = np.floor(10 * rg.random((2, 12))) #生成(2,12)数组,rg是随机数生成器
>>> a
array([[6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.],
       [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]])
>>> # a 水平分割成3组
>>> np.hsplit(a, 3)
[array([[6., 7., 6., 9.],
       [8., 5., 5., 7.]]), array([[0., 5., 4., 0.],
       [1., 8., 6., 7.]]), array([[6., 8., 5., 2.],
       [1., 8., 1., 0.]])]
>>> #  在第三列和第四列之后分割 `a`
>>> np.hsplit(a, (3, 4))
[array([[6., 7., 6.],
       [8., 5., 5.]]), array([[9.],
       [7.]]), array([[0., 5., 4., 0., 6., 8., 5., 2.],
       [1., 8., 6., 7., 1., 8., 1., 0.]])]

函数[vsplit]{.title-ref} 在垂直轴向分割数组, 函数[array_split]{.title-ref} 允许指定分割的轴.

拷贝和视图

在数组上运算或者操作数组时,有时候需要copy数组数据到新数组,有的时候并不需要这样copy。 对于初学者来说,这很困惑。 主要有下面3种cppy用例:

完全不复制

简单的赋值运算并不复制对象或者他们的数据

>>> a = np.array([[ 0,  1,  2,  3],
...               [ 4,  5,  6,  7],
...               [ 8,  9, 10, 11]])
>>> b = a            # no new object is created
>>> b is a           # a and b are two names for the same ndarray object
True

Python传递可变对象的引用,所以函数调用不需要复制数据

>>> def f(x):
...     print(id(x))
...
>>> id(a)  # id is a unique identifier of an object #doctest: +SKIP
148293216  # may vary
>>> f(a)   #doctest: +SKIP
148293216  # may vary

视图或者浅复制

不同的数组对象可以共享相同的数据。 这个view视图方法可以创建新的数组对象,新数组和原数组指向的是相同的数据 »> c = a.view() »> c is a False »> c.base is a # 数组 c 是拥有数据的 数组a 的视图 True »> c.flags.owndata False »> »> c = c.reshape((2, 6)) # 数组a的shape不变 »> a.shape (3, 4) »> c[0, 4] = 1234 # 数组a的数据也变化 »> a array([[ 0, 1, 2, 3], [1234, 5, 6, 7], [ 8, 9, 10, 11]])

数组切片返回的是它的一个视图:

>>> s = a[:, 1:3]
>>> s[:] = 10  # s[:] is a view of s. Note the difference between s = 10 and s[:] = 10
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

深复制

函数copy 对数组和它的数据进行一次完全的copy

>>> d = a.copy()  # 创建了新的具有新的数据的数组对象 a new array object with new data is created
>>> d is a
False
>>> d.base is a  # d并不和a共享任何信息
False
>>> d[0, 0] = 9999
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

有时候 copy 可以在数组切片后并且并不需要原数组的时候调用。比如, 假如a是一个巨大的中间结果数组, 最终结果b仅仅包含a的一小部分,那么在数组切片构造b的时候可以调用深复制操作

>>> a = np.arange(int(1e8))
>>> b = a[:100].copy()
>>> del a  # 在上面操作后, ``a`` 的内存可以被释放

如果上面使用的是b = a[:100],那么ab 引用, 那么即使 del a 被执行, a 还是会储存在内存中.

函数和方法总揽

下面是一些有用的Numpy函数和方法

Further reading