想要学好机器学习,我们需要熟练掌握python中的numpy库和pandas库。在numpy库中,有一个有意思且重要的知识点,即浅拷贝与深拷贝的联系与区分。
导入库+创建数据源
在进入正题前,我们首先导入numpy库,并创建一个操作数据源。
#导入numpy
import numpy as np
#创建数组a
a=np.arange(4)
print(a)
结果如下:
[0 1 2 3]
浅拷贝
数组a已经创建好了。我们将a的值浅拷贝给b。
b=a
print(a)
print(b)
结果如下:
[0 1 2 3]
[0 1 2 3]
我们可以看到,a和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都指向了同一个对象。
a与b都引用了该array对象,因此,在改变了内存中array的值后,a、b一起发生了变化。
这种将内存引用赋值给另一个变量的操作叫做浅拷贝。
深拷贝
深拷贝是指在赋值的时候,不把同一个内存对象的引用赋值给另一个变量,令两个变量所指向的对象不一样,更改值的时候不相互影响。
# 此时的a
print(a)
结果如下:
[9 1 2 3]
# 深拷贝
b = a.copy()
# 将a的第2个元素值也更改
a[1] = 9
print(a)
print(b)
结果如下:
[9 9 2 3]
[9 1 2 3]
copy()会创建a的一个副本,也就是创建一个一模一样的array对象,存储到内存的另一个地址中,然后将这个副本的地址赋值给b。
查看地址
查看地址的方法如下:
print('a引用的对象的地址:', id(a))
print('b引用的对象的地址:', id(b))
结果如下:
a引用的对象的地址: 2238964169344
b引用的对象的地址: 2238963438656
可以看出,深拷贝后,a和b所指向的对象是不一样的,它们的内存地址不一样。
再来看一下浅拷贝。
b = a
print('a引用的对象的地址:', id(a))
print('b引用的对象的地址:', id(b))
结果如下:
a引用的对象的地址: 2238964169344
b引用的对象的地址: 2238964169344
浅拷贝的内存地址是一样的。
我们在实际学习中还有比较简单的检验方案。如果相判断两个对象是不是指向同一个对象,可以用如下语句:(这里是浅拷贝)
print(b is a)
True
结果为True,说明b和a其实引用的是同一个对象。
接下来看看深拷贝。
b = a.copy()
print(b is a)
结果如下:
False
结果是False,说明b指向的对象已不再是a原来指向的对象。