NumPy 副本和视图

 

NumPy 副本和视图

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

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

视图一般发生在:

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

副本一般发生在:

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

无复制

简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同id()来访问它。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。

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

复制代码

import numpy as np

a=np.arange(6)

print('我们的数组是:')

print(a)

print('调用id()函数:')

print(id(a))

print('a赋值给b:')

b=a

print('调用id()函数:')

print(id(b))

print('改变b的形状:')

b.shape=3,2

print(b)

print('a的形状也修改了:')

print(a)

 

------------------执行以上程序,返回的结果为---------------

我们的数组是:
[0 1 2 3 4 5]


调用id()函数:
2174692600208


a赋值给b:
调用id()函数:
2174692600208


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


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

复制代码

视图或浅拷贝

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

复制代码

import numpy as np

#开始 a是一个3×2的数组

a=np.arange(6).reshape(3,2)

print('我们的数组是:')

print(a)

print('创建a的视图:')

b=a.view()

print(b)

print('a的id():')

print(id(a))

print('b的id():')

print(id(b))

print('改变b的形状:')

b.shape=2,3

print('b的形状:')

print(b)

print('a的形状:')

print(a)

 

------------------执行以上程序,返回的结果为---------------

我们的数组是:
[[0 1]
 [2 3]
 [4 5]]


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


a的id():
2097277414016


b的id():
2097280668656


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


a的形状:
[[0 1]
 [2 3]
 [4 5]]

复制代码

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

复制代码

import numpy as np

arr=np.arange(12)

print('我们的数组是:')

print(arr)

print('我们的切片:')

a=arr[3:]

b=arr[3:]

a[1]=123

b[2]=456

print(arr)

print(id(a),id(b),id(arr[3:]))

 

------------------执行以上程序,返回的结果为---------------

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


我们的切片:
[  0   1   2   3 123 456   6   7   8   9  10  11]


1891795293088 1889894133632 1889894132752

 

复制代码

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

副本或深拷贝

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

复制代码

import numpy as np

a=np.array([[1,20],[4,5],[7,8]])

print('数组a:')

print(a)

print('创建a的深层副本:')

b=np.copy(a)

print('数组b:')

print(b)

#b与a不共享任何内容

print('我们能够写入b来写入a吗?')

print(b is a)

print('修改b的内容:')

b[0,0]=100

print('数组b:')

print(b)

print('数组a:')

print(a)

 

------------------执行以上程序,返回的结果为---------------

数组a:
[[ 1 20]
 [ 4  5]
 [ 7  8]]


创建a的深层副本:
数组b:
[[ 1 20]
 [ 4  5]
 [ 7  8]]


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


修改b的内容:
数组b:
[[100  20]
 [  4   5]
 [  7   8]]


数组a:
[[ 1 20]
 [ 4  5]
 [ 7  8]]

复制代码

 

Python 中 list 的拷贝与 numpy 的 array 的拷贝

1.python中列表list的拷贝,会有什么需要注意的呢?

 

Python 变量名相当于标签名。

list2=list1 直接赋值,实质上指向的是同一个内存值。任意一个变量 list1(或list2)发生改变,都会影响另一个 list2(或list1)。

例如:

复制代码

>>> list1=[1,2,3,4,5,6]
>>> list2=list1
>>> list1[2]=88
>>> list1 [1, 2, 88, 4, 5, 6]
>>> list2
[1, 2, 88, 4, 5, 6]

复制代码

而 list3 和 list4 是通过切片对 list1 的复制操作,分别指向了新的值。任意改变 list3 或 list4 的值,不会影响其他。

2.要使用 ndarray 类型的数组,需要 from numpy import * 引用工具包 numpy。

而对 ndarray 类型的数据进行拷贝时,跟 list 类型有一点区别。

数组切片是原始数组的视图,这意味着数据不会被复制,视图上的任何修改都会被直接反映到源数组上。

array1, array2, array3, array4 实际指向同一个内存值,任意修改其中的一个变量,其他变量值都会被修改。

若想要得到的是 ndarray 切片的一份副本而非视图,就需要显式的进行复制操作函数 copy()。

例如:

array5=array1.copy()      # 对原始的 array1 的复制
array6=array1[1:4].copy() # 对切片 array1[1:4] 的复制

那么,修改 array5 或 array6,就不会影响 array1。

复制代码

import numpy as np
a = np.arange(4)
b = a
# 改变a中第一个元素的值
a[0] = 9
print(a)
print(b)

 

------------------执行以上程序,返回的结果为---------------

[9 1 2 3]
[9 1 2 3]

复制代码

可以看到,改变 a 后,b 的值也跟着变了,这是为什么呢?

实际上,变量 a 中并没有存储任何的值,它只是指向了一个内存地址,而这个地址里存储着 array 具体的内容,当把a赋值给b的时候,实际上是把 a 指向内存中某对象的链接赋给了 b,也就是说,现在 a 和 b 都指向了同一个对象。

因此,在改变了内存中 array 的值后,而 a 与 b 都引用了该 array 对象,所以都一起发生了变化。

这种将内存引用赋值给另一个变量的操作叫做浅拷贝。

那什么是深拷贝呢,其实就是在赋值的时候,不把同一个内存对象的引用赋值给另一个变量,令两个变量所指向的对象不一样,更改值的时候不相互影响,这种操作就是深拷贝。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值