python的复制方式有两种:
- 浅复制:只复制对象引用,不复制对象本身。
- 深复制:调用copy模块的deepcopy方法来执行复制。
深浅赋值其实都是开启新的空间来存放,只是内部元素的指向地址的区别。
如果内部元素是不可变类型(number / string / tuple),则两个元素的地址相同;
如果内部元素是可变类型(list / set / dir),若是浅赋值,则两个元素地址相同,若是深复制,则地址不同。
关于深浅复制其实是对可变类型的讨论。
列表对象的浅复制可以由以下方式来实现:
“*”运算符代表浅复制。执行运算时,意味着新列表中每个索引位置都会引用旧列表中每个索引位置的元素。
x = [23,56]
y = x * 3
■ y 输出【23,56,23,56,23,56】,表示列表y的索引 0,2,4指向列表x的第一个元素23,列表y的索引1,3,5指向列表x的第二个元素56
切片不会复制元素,而是创建一个新列表,再把原列表的每个元素指定给新列表的索引,以便进行引用。
使用列表对象提供的copy()方法实现浅复制
x = [11,[11,22],[23,45,67]]
y = x[:]
z = x.copy()
使用copy模块的copy()方法时,一般对象是复制对象引用,元素id相同;若列表中含有列表,则会以浅复制来处理。
a = [8, 9, 0]
b = copy.copy(a)
print(a,b)
# [8, 9, 0] [8, 9, 0]
a[0] = 5
print(a,b)
# [5, 9, 0] [8, 9, 0]
a = [8, [22,33], 0]
b = copy.copy(a)
print(a,b)
# [8, [22, 33], 0] [8, [22, 33], 0]
a[0] = 5
print(a,b)
# [5, [22, 33], 0] [8, [22, 33], 0]
a[1][0] = 123456
print(a,b)
# [5, [123456, 33], 0] [8, [123456, 33], 0]
a = [8, [22, 33], 0, ['a', 'b']]
b = a # 赋值,对象的引用
c = copy.copy(a) # 对象复制,浅复制
d = copy.deepcopy(a)
print(a, b, c, d, sep='\n')
# a b c d均为:[8, [22, 33], 0, ['a', 'b']]
a.append(5)
print(a, b, c, d, sep='\n')
## a,b均为:[8, [22, 33], 0, ['a', 'b'], 5]
## c,d均为:[8, [22, 33], 0, ['a', 'b']]
a[3].append('c')
print(a, b, c, d, sep='\n')
## a,b均为:[8, [22, 33], 0, ['a', 'b', 'c'], 5]
## c为:[8, [22, 33], 0, ['a', 'b', 'c']]
## d为:[8, [22, 33], 0, ['a', 'b']]
a[0] = 4
a[3][0] = 'aaaa'
a.insert(0, [1, 2])
print(a, b, c, d, sep='\n')
# a,b均为:[[1, 2], 4, [22, 33], 0, ['aaaa', 'b', 'c'], 5]
# c为:[8, [22, 33], 0, ['aaaa', 'b', 'c']]
# d为: [8, [22, 33], 0, ['a', 'b']]