python中的浅拷贝和深拷贝

对python中的浅拷贝和深拷贝的一些理解

抛出问题

  在使用python创建列表时,出现了一些问题,下面是我创建列表矩阵的三种方式:

#第一种方式
A = [0] * 3
for i in range(3):
    A[i] = [0] * 3
print(A)
A[0][1] = 1
print(A)
#第二种方式
B = [[0] * 3] * 3
print(B)
B[0][1] = 1
print(B)
#第三种方式,使用列表推导式
C = [[0] * 3 for i in range(3)]
print(C)
C[0][1] = 1
print(C)

  然而,运行出来的结果是这样的:

[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 1, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 1, 0], [0, 0, 0], [0, 0, 0]]

  第二种方法将矩阵中中间一列的值全都改变了,显然矩阵AB并不等价,查找资料后发现第二种方法只是对同一列表进行了三次引用。下面来解释一下浅拷贝和深拷贝的相关用法。

浅拷贝

  我们通过代码来理解一下:

#下面介绍第一种浅拷贝方法,列表里的copy()方法
#创建一个一维列表,命名为x
x = [1, 2, 3, 4, 5]
x_copy = x.copy()
x[0] = 0
print(x)
print(x_copy)
#创建一个二维列表,命名为y
y = [[1, 2, 3], [4, 5, 6]]
y_copy = y.copy()
y[0][0] = 0
print(y)
print(y_copy)

  在pycharm中运行代码结果如下:

[0, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[[0, 2, 3], [4, 5, 6]]
[[0, 2, 3], [4, 5, 6]]

  我们可以发现对于一维列表,改变x的值并不影响x_copy的值,但对于二维列表改变y的值却也改变了y_copy的值。为什么呢?因为浅拷贝仅仅是拷贝了外层的对象,而对内层对象只是引用了一下。上面代码使用copy()方法拷贝二维列表的过程可以表示如下图:
在这里插入图片描述
  下面来介绍第二种和第三种浅拷贝的方法:

#第二种浅拷贝方法,使用copy包里面的copy函数
import copy
y = [[1, 2, 3], [4, 5, 6]]
y_copy = copy.copy(y)
y[0][0] = 0
print(y)
print(y_copy)
#第三种浅拷贝方法,切片方法
y_copy = y[ : ]
y[0][0] = 0
print(y)
print(y_copy)

  运行结果如下,分析与第一种方法一样,这里不再赘述啦。

[[0, 2, 3], [4, 5, 6]]
[[0, 2, 3], [4, 5, 6]]
[[0, 2, 3], [4, 5, 6]]
[[0, 2, 3], [4, 5, 6]]

深拷贝

  深拷贝需要使用copy包里面的deepcopy()函数:

import copy
y = [[1, 2, 3], [4, 5, 6]]
y_copy = copy.deepcopy(y)
y[0][0] = 0
print(y)
print(y_copy)

  运行结果如下:

[[0, 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]

  关于为什么不直接广泛使用深拷贝的问题,up主给出的理由是因为深拷贝运行速度较慢。

我的问题出在了这里!!!

  两个矩阵创建图这样表示:
在这里插入图片描述
  所以创建B矩阵实质上是对创建出来的一维矩阵[0,0,0]进行了三次引用,任意一次引用改变一维矩阵的值都会使得三行全改变。
  另外介绍一下 is 运算符,用于检验两个变量是不是指向的同一个变量,这里一定要记住:字符串是不能改变的,用is运算符检验会返回 True ,而列表是可以改变的,会返回 False。还有就是 y = x 命令是将 y 指向 x 指向的对象,是引用关系,不是拷贝。
  欢迎大家批评指正,大家一起学习一起进步哇!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值