Python列表复制【地址、深浅拷贝】

Python列表复制【赋值、深浅拷贝】

假设 需 复制 列表 a = [1, 2, [3, 4], 5]

1. 赋值

顾名思义,将 a 的地址也一并复制过去了,即当 a 发生改变时,b 也会改变,如:

a = [1, 2, [3, 4], 5]
b = a
print(a,b)
a[0] = 0
print(a,b)

2. 浅拷贝

当 a 中的单个数字发生变化时,c,d,e,f 不会改变;但当 a 中的子列表发生变化时,c,d,e,f 也跟着变化,先上代码:

a = [1, 2, [3, 4], 5]
c = a[:]        # 用切片  或者 c = [ x for x in a]
d = a.copy()    # 用列表的 copy 方法
e = list(a)     # 用 list 方法   list() 方法用于将元组转换为列表。
import copy
f = copy.copy(a)    # 用 copy 库
print(c,d,e,f)
# 修改 a 
a[0] = 0
print(a)
print(c,d,e,f)
# 修改 a 的子列表
a[2][1] = 8
print(a)
print(c,d,e,f)

结果如下图:
结果

如上图所示,中间那个列表[3,4]是单独分配了一块空间,然后从第一层列表中去引用地址,复制的 d 也是引用的地址,所以真实的值一变,两个列表的内部列表的值也就变了。

简单理解就是:
浅拷贝,是它仅仅只拷贝了一层,拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已

扩展:浅复制要分两种情况进行讨论:
1)当浅复制的值是不可变对象(字符串、元组、数值类型)时和“赋值”的情况一样,对象的id值(id()函数用于获取对象的内存地址)与浅复制原来的值相同。

2)当浅复制的值是可变对象(列表、字典、集合)时会产生一个“不是那么独立的对象”存在。有两种情况:

     第一种情况:复制的对象中无复杂子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

     第二种情况:复制的对象中有复杂子对象(例如列表中的一个子元素是一个列表),如果不改变其中复杂子对象,浅复制的值改变并不会影响原来的值。 但是改变原来的值中的复杂子对象的值会影响浅复制的值。

注:该段from Python中的赋值(复制)、浅拷贝与深拷贝

3. 深拷贝

深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。

所以改变原有被复制对象不会对已经复制出来的新对象产生影响.

a = [1, 2, [3, 4], 5]
import copy
g = copy.deepcopy(a)	# copy模块中的deepcopy函数
print(a)
print(g)
# 修改 a 的非子列表元素
a[0] = 0
print('----------修改 a 的非子列表元素-------------')
print(a)
print(g)
# 修改 a 的子列表元素
a[2][1] = 8
print('----------修改 a 的子列表元素-------------')
print(a)
print(g)
# 无论 a 怎么变化,  g 都不会改变

结果如下图所示:
深拷贝结果

总结

  1. 采用赋值方法,拷贝的列表随原列表变化而变化;
  2. 采用浅拷贝方法,当外层元素变化时,拷贝的列表不会随原列表变化而变化;内层元素变化时,浅拷贝才会变化;
  3. 无论原列表怎么变化,深拷贝都不会改变。

猜你喜欢

转载自blog.csdn.net/qq_38828370/article/details/119826285
今日推荐