目录
  1. 1. 浅拷贝及深拷贝的理解
  2. 2. 以list为例的实际拷贝情况
    1. 2.1. 浅拷贝的几种方法(对于一维来说是有作用的):
    2. 2.2. 深拷贝:deepcopy()
  3. 3. np.array直接复制的话是是深拷贝
Python中浅拷贝和深拷贝

浅拷贝及深拷贝的理解

浅拷贝是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
In [1]: import copy

In [2]: a = [1,2,3]

In [3]: b = [11,22,33]

In [4]: c = [a,b]

In [5]: c
Out[5]: [[1, 2, 3], [11, 22, 33]]

In [6]: d = copy.copy(c)

In [7]: d
Out[7]: [[1, 2, 3], [11, 22, 33]]

In [8]: id(c) # 用来显示a指向的数据内存地址
Out[8]: 1803852506696

In [9]: id(d) # 用来显示b指向的数据内存地址
Out[9]: 1803850684680

In [10]: a.append(4) # 向a列表中添加一个数据

In [11]: d
Out[11]: [[1, 2, 3, 4], [11, 22, 33]]
# d是从c拷贝过来的,[a,b]列表指向c。d拷贝来的只是引用,所以数据会发生变化
因为是浅拷贝,所以只要通过一个引用的修改,那么另外一个变量就能看到的数据变化。
比如:有一个苹果,是小明和小马共有的,如果小马吃了一口苹果,小明的苹果也会少

深拷贝是对于一个对象所有层次的拷贝(递归)

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In [45]: a = [1,2,3]

In [46]: b = [11,22,33]

In [47]: c = [a,b]

In [48]: d = copy.deepcopy(c)

In [49]: id(c) # c列表的内存地址
Out[49]: 1803854612488

In [50]: id(d) # d列表的内存地址
Out[50]: 1803851663432

In [51]: a.append(4) # 向a添加一个数据

In [52]: c
Out[52]: [[1, 2, 3, 4], [11, 22, 33]] # 可以看出原始数据中的a列表被影响了

In [53]: d
Out[53]: [[1, 2, 3], [11, 22, 33]] # 而经过深拷贝的a列表不受影响

浅拷贝对不可变类型和可变类型的copy不同

  1. copy.copy对于可变类型(\列表、字典**),会进行浅拷贝。
  2. copy.copy对于不可变类型(\元祖、数字、字符串**),不会拷贝,仅仅是指向。

如果c是元祖,那么copy时仅仅是copy元祖的\引用**

而deepcopy依然是深copy,使用\递归**copy所有

以list为例的实际拷贝情况

如果用=直接赋值,是非拷贝方法。这两个列表是等价的,修改其中任何一个列表都会影响到另一个列表。

浅拷贝的几种方法(对于一维来说是有作用的):

  1. copy()

    对于list的第一层,是实现了深拷贝,但对于嵌套的list,仍然是浅拷贝。这其实很好理解,内层的list保存的是地址,复制过去的时候是把地址复制过去了。嵌套的list在内存中指向的还是同一个。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    old = [1,[1,2,3],3]
    new = old.copy()
    print('Before:')
    print(old)
    print(new)
    new[0] = 3
    new[1][0] =3
    print('After:')
    print(old)
    print(new)
    输出:
    Before:
    [1, [1, 2, 3], 3]
    [1, [1, 2, 3], 3]
    After:
    [1, [3, 2, 3], 3]
    [3, [3, 2, 3], 3]
  2. 使用链表生成式,也是一种浅拷贝

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    old = [1,[1,2,3],3]
    new = [i for i in old]
    print('Before')
    print(old)
    print(new)
    new[0] = 3
    new[1][0] = 3
    print('After')
    print(old)
    print(new)
  3. 使用切片

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    old = [1,[1,2,3],3]
    new = old[:]
    print('Before:')
    print(old)
    print(new)
    new[0] = 3
    new[1][0] = 3
    print('After:')
    print(old)
    print(new)

深拷贝:deepcopy()

1
2
3
4
5
6
7
8
9
10
11
import copy
old = [1,[1,2,3],3]
new = copy.deepcopy(old)
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)

np.array直接复制的话是是深拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a = np.array([[0,1,2],
[3,4,5],
[6,7,8]])
b = a*2
print (a)
print (b)
a[0][0] = 2
print (a)
print (b)

output:
[[0 1 2]
[3 4 5]
[6 7 8]]
[[ 0 2 4]
[ 6 8 10]
[12 14 16]]

[[2 1 2]
[3 4 5]
[6 7 8]]
[[ 0 2 4]
[ 6 8 10]
[12 14 16]]
文章作者: HazardFY
文章链接: http://hazardfy.github.io/2019/11/16/Python中浅拷贝和深拷贝/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HazardFY's BLOG
打赏
  • 微信
  • 支付寶