在操作数组的时候返回的不是视图就是副本。

副本:复制

视图:链接

 

副本是一个数据的完整拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。

视图是数据的一个别称或引用,通过该别称或引用亦可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。

 

视图一般发生在:

  • 1、numpy 的切片操作返回原数据的视图。
  • 2、调用 ndarray 的 view() 函数产生一个视图。

副本一般发生在:

  • Python 序列的切片操作,调用deepCopy()函数。
  • 调用 ndarray 的 copy() 函数产生一个副本。

 

赋值

赋值操作,两个变量a, b都指向同一个内存地址, b与原始数组a的id()相同。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。

一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。

import numpy as np

a = np.arange(6)
b = a
print(数组a:,a)
print(数组b:,b)

print(a 调用 id() 函数:,id(a))
print(b 调用 id() 函数:,id(b))

b.shape = 3, 2
print(修改 b 的形状:)
print(b)
print(a 的形状也修改了:)
print(a)

输出结果为:

数组a: [0 1 2 3 4 5]
数组b: [0 1 2 3 4 5]
a 调用 id() 函数: 2026424909056
b 调用 id() 函数: 2026424909056


修改 b 的形状:
[[0 1]
[2 3]
[4 5]]


a 的形状也修改了:
[[0 1]
[2 3]
[4 5]]

 

视图或浅拷贝

Numpy的切片操作会返回原数据的视图,切片产生的视图是原视图的一部分视图,对视图的修改会直接反映到原数据中,但它们的id是不同的。也就是说,视图虽然指向原数据,但是他们和赋值引用还是有区别的。

ndarray.view() 方会创建一个新的数组对象,该方法创建的新数组的维数更改不会更改原始数据的维数。

import numpy as np

# 最开始 a 是个 3X2 的数组
a = np.arange(6).reshape(3, 2)
print(数组 a:)
print(a)
print(
)

b = a.view()
print(创建 a 的视图b:)
print(b)
print(
)

print(a 的 id():,id(a))
print(b 的 id():,id(b))
print(
)

# 修改 b 的形状,并不会修改 a
b.shape = 2, 3
print(修改形状后的b:)
print(b)
print(
)

print(修改b形状后的a:)
print(a)

输出结果为:

数组 a:
[[0 1]
[2 3]
[4 5]]


创建 a 的视图b:
[[0 1]
[2 3]
[4 5]]


a 的 id(): 1601808711552
b 的 id(): 1601809504256


修改形状后的b:
[[0 1 2]
[3 4 5]]


修改b形状后的a:
[[0 1]
[2 3]
[4 5]]

 

使用切片创建视图修改数据会影响到原始数组:

import numpy as np

arr = np.arange(12)
print(我们的数组:,arr)
print(
)

a = arr[3:]
b = arr[3:]
print(切片a:,a)
print(切片b:,b)
print(
)

a[1] = 123
b[2] = 234
print(修改后的数组arr:)
print(arr)
print(修改后的数组a:)
print(a)
print(修改后的数组b:)
print(b)
print(
)


print(a的id:,id(a))
print(b的id:,id(b))
print(arr的id:,id(arr))

输出结果为:

我们的数组: [ 0 1 2 3 4 5 6 7 8 9 10 11]


切片a: [ 3 4 5 6 7 8 9 10 11]
切片b: [ 3 4 5 6 7 8 9 10 11]


修改后的数组arr:
[ 0 1 2 3 123 234 6 7 8 9 10 11]
修改后的数组a:
[ 3 123 234 6 7 8 9 10 11]
修改后的数组b:
[ 3 123 234 6 7 8 9 10 11]


a的id: 1173376024448
b的id: 1173376023968
arr的id: 1173376023888

 

变量 a,b 都是 arr 的一部分视图,对视图的修改会直接反映到原数据中。但是我们观察 a,b 的 id,他们是不同的,也就是说,视图虽然指向原数据,但是他们和赋值引用还是有区别的。

 

副本或深拷贝

ndarray.copy() 创建一个副本。 对副本数据进行修改,不会影响到原始数据,它们物理内存不一样。

import numpy as np

a = np.array([[10, 10], [2, 3], [4, 5]])
print(数组 a:)
print(a)
print(
)

b = a.copy()
print(创建 a 的副本数组 b:)
print(b)
print(
)

# b 与 a 不共享任何内容
print(我们能够写入 b 来写入 a 吗?)
print(b is a)
print(
)


b[0, 0] = 100
print(修改副本b:)
print(b)
print(
)

print(修改副本b后,a数组不变:)
print(a)

输出结果为:

数组 a:
[[10 10]
[ 2 3]
[ 4 5]]


创建 a 的副本数组 b:
[[10 10]
[ 2 3]
[ 4 5]]


我们能够写入 b 来写入 a 吗?
False


修改副本b:
[[100 10]
[ 2 3]
[ 4 5]]


修改副本b后,a数组:
[[10 10]
[ 2 3]
[ 4 5]]