一、列表的复制
列表的复制一共有三种方法,直接赋值,深拷贝与浅拷贝。
1、直接赋值
直接赋值非常简单,就是把a变量的引用传递给b变量,即变量a和b指向同一个内存空间,因此a与b的变化是同步的。a的改变能引起b的改变,同时,b列表的改变也能引起a的改变。
a=[3,(5,8),999,[43,24,56],'apple']
b=a
a.append(100)
print(a)
##[3, (5, 8), 999, [43, 24, 56], 'apple', 100]
print(b)
##[3, (5, 8), 999, [43, 24, 56], 'apple', 100]
#
#
a[3].append(1)
print(a)
##[3, (5, 8), 999, [43, 24, 56, 1], 'apple']
print(b)
#[3, (5, 8), 999, [43, 24, 56, 1], 'apple']
b.append(2)
print(a)
#[3, (5, 8), 999, [43, 24, 56], 'apple', 2]
print(b)
#[3, (5, 8), 999, [43, 24, 56], 'apple', 2]
b[3].append(6)
print(a)
#[3, (5, 8), 999, [43, 24, 56, 6], 'apple']
print(b)
#[3, (5, 8), 999, [43, 24, 56, 6], 'apple']
直接赋值方法普遍存在于 Python 之中,这种赋值的方式实现了 “假装” 拷贝,真实的情况还是两个变量和同一个对象之间的引用关系。
2、浅拷贝
浅拷贝:浅拷贝创建一块新的内存空间,内存空间中元素的地址均是父对象元素地址的拷贝。如果父元素a的子对象改变了,那么拷贝对象c的子对象同时也会改变。
a=[3,(5,8),999,[43,24,56],'apple']
c=a.copy()
a[3].append(100)
print(a)
#[3, (5, 8), 999, [43, 24, 56, 100], 'apple']
print(c)
#[3, (5, 8), 999, [43, 24, 56, 100], 'apple']
但是,如果a对象中增加了新的元素(c中没有此元素的引用),那么a的变化将不会使c发生改变。(因为新元素不是父元素)
a=[3,(5,8),999,[43,24,56],'apple']
c=a.copy()
a.append(100)
print(a)
#[3, (5, 8), 999, [43, 24, 56], 'apple', 100]
print(c)
#[3, (5, 8), 999, [43, 24, 56], 'apple']
#id(a)
#Out: 2131336425352
#id(c)
#Out: 2131337455560
id(a[3])
#Out:2131337500104
id(c[3])
#Out:2131337500104
c列表只是复制了a别表的一层元素,对于深层的列表、字典、元组只是把地址绑定到当前下标而不是完全递归复制。
实现浅拷贝的方法有:
a.copy()
c=a[:] #使用切片
c=[i for i in a] #列表推导式
c=[i,for i in range(len(a))] #遍历a列表
3、深拷贝
深拷贝完全拷贝了父对象及子对象,同时指向一个新的内存空间地址。无论多少层,无论怎样的形式,得到的新列表都是和原来无关的,这是最安全最清爽最有效的方法。
import copy
a=[3,(5,8),999,[43,24,56],'apple']
c=copy.deepcopy(a)
a.append(100)
print(a)
#[3, (5, 8), 999, [43, 24, 56], 'apple', 100]
print(c)
#[3, (5, 8), 999, [43, 24, 56], 'apple']
a[3].append(10)
print(a)
[3, (5, 8), 999, [43, 24, 56, 10], 'apple', 100]
print(c)
[3, (5, 8), 999, [43, 24, 56], 'apple']
import copy
a=[3,(5,8),999,[43,24,56],'apple']
c=copy.deepcopy(a)
c.append(100)
print(a)
#[3, (5, 8), 999, [43, 24, 56], 'apple']
print(c)
#3, (5, 8), 999, [43, 24, 56], 'apple', 100]