浅复制和深复制

Python中,复制有以下几种方法

1.赋值复制

>>>a = [1, 2, 3]
>>>b = a
>>>b
[1, 2, 3]

此时的复制,b仅仅是指向了a所在的内存空间,在内存中,并没有申请一处新的空间来存储列表b,a和b在内存中的id是相同的,如果a发生改变,b也会跟着改变。

>>>id(a)
2604172565640
>>>id(b)
2604172565640
>>>
>>>a.append(4)
>>>a
[1, 2, 3, 4]
>>>b
[1, 2, 3, 4]

赋值复制,存在一种特殊情况,a1 = a * 1 , 也可以实现浅复制,此时a和a1在不同的内存地址,a中元素改变,a1不变,但是,如果a中存在子列表,子列表中还是指向原地址,a中子列表改变,a1中的子列表跟着改变。

>>>a1 = a * 1
>>>a1

>>>id(a1)
2604172509960
>>>id(a)
2604172565640

2.切片复制(仅适用于可切片的的对象)(浅复制)

利用列表的可以切片的特性,把列表的所有元素切片,赋值给c,间接达到复制的目的;此时在系统在内存中新申请了一片内存,用来你存放c。a改变,不影响c。

>>>a.append([5])
>>>a 
[1, 2, 3, 4, [5]]
>>>c = a[:]
>>>c
[1, 2, 3, 4, [5]]
>>>id(c)
2604172381000
>>>a.append(6)
>>>a
[1, 2, 3, 4, [5], 6]
>>>c
[1, 2, 3, 4, [5]]

此时,也仅仅是复制了顶层内存地址,如果存在子列表,子列表中还是指向原地址。

>>>a[4].append(1)
>>>a
[1, 2, 3, 4, [5, 1], 6]
>>>c
[1, 2, 3, 4, [5, 1]]

>>>id(a[4])
2604172564808
>>>id(c[4])
2604172564808

3.使用copy模块中的函数

      1)copy.copy()  浅复制 ,复制了目标的顶层对象,内存id不同,a中添加元素,d不变。

>>>import copy
>>>d = copy.copy(a)
>>>d
[1, 2, 3, 4, [5, 1], 6]
>>>id(d)
2604172700552
>>>id(a)
2604172565640

# a改变,d不变
>>>a.append(7)
>>>a
[1, 2, 3, 4, [5,1], 6, 7]
>>>d
[1, 2, 3, 4, [5, 1], 6]

但是,当a中存在子列表时,子列表中元素发生改变,d中的子列表会跟着改变,因为copy.copy()仅复制了顶层数据的内存地址,并没有复制下层子列表中元素的内存地址;子列表中的元素,指向同一片内存空间。

>>>a[4].append(7)
>>>a
[1, 2, 3, 4, [5, 1 , 7], 6, 7]
>>>d
[1, 2, 3, 4, [5, 1, 7], 6]

>>>id(a[4])
1984975808
>>>id(d[4])
1984975808

        2)copy.deepcopy() 深复制,从顶层到底层,所有的全部复制,和原数据除了值相等,没有其他任何关系。a中子列表内元素改变,对深复制的e没影响

>>>e = copy.deepcopy(a)
>>>e
[1, 2, 3, 4, [5, 1 , 7], 6, 7]
>>>id(a)
2604172565640
>>>id(e)
2604172381576

>>>a[4].append(8)
>>>a
[1, 2, 3, 4, [5, 1 , 7, 8], 6, 7]
>>>e
[1, 2, 3, 4, [5, 1 , 7], 6, 7]

>>>id(a[4])
2604172564808
>>>id(e[4])
2604172831240

猜你喜欢

转载自blog.csdn.net/qq_34172340/article/details/81713106
今日推荐