Python直接赋值、浅拷贝和深拷贝以及切片

参考
https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html

1. 直接赋值

直接赋值: b = a , a 和 b 都指向同一个对象,则若改变a或b,另一个变量的值会跟着改变。

直接赋值:其实就是对象的引用(别名)。

直接赋值

例:

1.1 列表赋值实例

1
2
3
4
5
6
7
>>> a = [1,2,3]
>>> b = a

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

👆 改变a -> b会跟着变;改变b -> a会跟着变

1.2 字典赋值实例

1
2
3
4
5
6
7
>>> a = {1:[1,2,3]}
>>> b = a

>>> a[1].append(4)
>>> b[1].append(5)
>>> a, b
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4, 5]})

👆 改变a -> b会跟着变;改变b -> a会跟着变

2. 浅拷贝

浅拷贝: b = a.copy() ,a 和 b 是一个独立的对象,但他们的子对象还是指向同一对象(是引用)。浅拷贝拷贝父对象,改变其中一个,另一个不会变,但如果a中还有子对象,则改变子对象中的内容,另一个的子对象中的内容会跟着变 (见下面示例)。

浅拷贝(copy):拷贝父对象,不会拷贝对象内部的子对象。(即拷贝了父对象,现在改变父对象的话,不会影响到另一个变量的值,但由于子对象没有被拷贝,改变一个变量的子对象的值会影响另一个变量的值)

浅拷贝

例:

2.1 列表浅拷贝实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> a = [1,2,3]
>>> b = a.copy()

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

注:切片操作其实是一种浅拷贝操作
>>> a = [1,2,3]
>>> b = a[:]
>>> b[0] = 4
>>> a,b
([1, 2, 3], [4, 2, 3])

👆 改变a -> b不会跟着变;改变b -> a不会跟着变

2.2 字典浅拷贝实例

1
2
3
4
5
6
7
>>> a = {1:[1,2,3]}
>>> b = a.copy()

>>> a[1].append(4)
>>> b[1].append(5)
>>> a,b
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4, 5]})

👆 改变子对象内容时:改变a -> b会跟着变;改变b -> a会跟着变

1
2
3
4
>>> a[2] = [2,2,2]
>>> b[3] = [3,3,3]
>>> a, b
({1: [1, 2, 3, 4, 5], 2: [2, 2, 2]}, {1: [1, 2, 3, 4, 5], 3: [3, 3, 3]})

👆 改变父对象内容时:改变a -> b不会跟着变;改变b -> a不会跟着变

3. 深拷贝

深度拷贝:b = copy.deepcopy(a),a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。无论改变a中的任何内容,b中都没有影响,反之亦然。

深拷贝(deepcopy):copy模块的deepcopy方法,完全拷贝了父对象及其子对象。

深拷贝

例:

2.1 列表深拷贝实例

1
2
3
4
5
6
7
8
>>> import copy 
>>> a = [1,2,3]
>>> b = copy.deepcopy(a)

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

👆 改变a -> b不会跟着变;改变b -> a不会跟着变

2.2 字典深拷贝实例

1
2
3
4
5
6
7
8
>>> import copy 
>>> a = {1:[1,2,3]}
>>> b = copy.deepcopy(a)

>>> a[1].append(4)
>>> b[1].append(5)
>>> a,b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 5]})

👆 改变子对象内容时:改变a -> b不会跟着变;改变b -> a不会跟着变

1
2
3
4
>>> a[2] = [2,2,2]
>>> b[3] = [3,3,3]
>>> a,b
({1: [1, 2, 3, 4], 2: [2, 2, 2]}, {1: [1, 2, 3, 5], 3: [3, 3, 3]})

👆 改变父对象内容时:改变a -> b不会跟着变;改变b -> a不会跟着变

4. 更多实例

1
2
3
4
5
6
7
8
9
10
11
12
13
import copy
a = [1,2,3,4,['a','b']] # 原始对象
b = a # 赋值,传对象的引用
c = a.copy() # 对象拷贝,浅拷贝
d = copy.deepcopy(a) # 对象拷贝,深拷贝

a.append(5) # 修改对象a
a[4].append('c') #修改对象a中的['a','b']数组对象

print('a = ', a)
print('b = ', b)
print('c = ', c)
print('d = ', d)

输出结果为:

1
2
3
4
a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]

5. 切片操作

Python切片操作可作用于 list(包括 tuple, string)

切片操作相当于浅拷贝

例:

1
2
3
4
5
6
a = [1,2,[3]]
b = a[:]
a.append(5)
a[2].append(4)
print('a = ', a)
print('b = ', b)

输出结果为:

1
2
a =  [1, 2, [3, 4], 5]
b = [1, 2, [3, 4]]