Loading

python中的浅拷贝和深拷贝

1. 浅拷贝

  • 浅拷贝是对于一个对象的顶层拷贝

通俗的理解是:拷贝了引用,并没有拷贝内容。

在ipython3进程验证:

In [1]: a = [11, 22]

In [2]: b = a  # 赋值语句相当于一个简单的浅拷贝

In [3]: id(a)
Out[3]: 139773824898824

In [4]: id(b)
Out[4]: 139773824898824

In [5]: import copy

In [6]: c = copy.copy(a) # 进行浅拷贝

In [7]: id(c)
Out[7]: 139773809263624

In [8]: d = [a, c]

In [9]: id(d)
Out[9]: 139773809207944

In [10]: e = copy.copy(d)

In [11]: id(e[0])
Out[11]: 139773824898824

In [12]: id(e[1])
Out[12]: 139773809263624

2. 深拷贝

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

在ipython3中验证:

In [1]: import copy

In [2]: a = [11, 22]

In [3]: b = copy.deepcopy(a)  # 对a进行深拷贝

In [4]: id(a)
Out[4]: 140025000141512

In [5]: id(b)
Out[5]: 140025000095880

In [6]: a.append(33)

In [7]: a
Out[7]: [11, 22, 33]

In [8]: b
Out[8]: [11, 22]

进一步理解深拷贝:

In [9]: a = [11, 22]

In [10]: b = [33, 44]

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

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

In [13]: id(a)
Out[13]: 140025000090632

In [14]: id(b)
Out[14]: 140025000091080

In [15]: id(c)
Out[15]: 140025015772744

In [16]: id(d)
Out[16]: 140025015768840

In [17]: id(d[0])
Out[17]: 140025000088136

In [18]: id(d[1])
Out[18]: 140025015702856

In [19]: a.append(66)

In [20]: a
Out[20]: [11, 22, 66]

In [21]: c
Out[21]: [[11, 22, 66], [33, 44]]

In [22]: d
Out[22]: [[11, 22], [33, 44]]

3. 拷贝的其他方式

  • 分片表达式可以赋值一个序列
In [23]: a = [11, 22]

In [24]: b = [33, 44]

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

In [26]: d = c[:]

In [27]: id(a)
Out[27]: 140025015770376

In [28]: id(b)
Out[28]: 140025000088200

In [29]: id(c)
Out[29]: 140025015698248

In [30]: id(d)
Out[30]: 140025000087624

In [31]: id(d[0])
Out[31]: 140025015770376

In [32]: id(d[1])
Out[32]: 140025000088200

In [33]: a.append(66)

In [34]: a
Out[34]: [11, 22, 66]

In [35]: c
Out[35]: [[11, 22, 66], [33, 44]]

In [36]: d
Out[36]: [[11, 22, 66], [33, 44]]

从上可知分片表达式也是浅拷贝

  • 字典的copy方法可以拷贝一个字典
In [38]: d = dict(name="zhangsan", age = 10)

In [39]: co = d.copy()

In [40]: id(d)
Out[40]: 140025000227144

In [41]: id(co)
Out[41]: 140025015714504

In [42]: d
Out[42]: {'name': 'zhangsan', 'age': 10}

In [43]: co
Out[43]: {'name': 'zhangsan', 'age': 10}

In [45]: d = dict(name="zhangsan", ages=[11,22])

In [46]: co = d.copy()

In [48]: d["ages"].append(33)

In [50]: d
Out[50]: {'ages': [11, 22, 33], 'name': 'zhangsan'}

In [51]: co
Out[51]: {'ages': [11, 22, 33], 'name': 'zhangsan'}

4. 注意点

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

  1. copy.copy对于可变类型,会进行浅拷贝
  2. copy.copy对于不可变类型,不会拷贝,仅仅是指向
In [88]: a = [11,22,33]
In [89]: b = copy.copy(a)
In [90]: id(a)
Out[90]: 59275144
In [91]: id(b)
Out[91]: 59525600
In [92]: a.append(44)
In [93]: a
Out[93]: [11, 22, 33, 44]
In [94]: b
Out[94]: [11, 22, 33]


In [95]: a = (11,22,33)
In [96]: b = copy.copy(a)
In [97]: id(a)
Out[97]: 58890680
In [98]: id(b)
Out[98]: 58890680

深拷贝对于全部是不可变类型,不会拷贝,仅仅拷贝指向,对于只要其中含有可变类型就会递归拷贝其中的内容。

In [81]: a = (11, 22)

In [82]: b = copy.deepcopy(a)

In [83]: id(a)
Out[83]: 140025015658888

In [84]: id(b)
Out[84]: 140025015658888

In [85]: a = [11, 22]

In [86]: b = (a, 33)

In [87]: c = copy.deepcopy(b)

In [88]: b
Out[88]: ([11, 22], 33)

In [89]: c
Out[89]: ([11, 22], 33)

In [90]: id(b)
Out[90]: 140025000007816

In [91]: id(c)
Out[91]: 140025000005832

In [92]: id(b[0])
Out[92]: 140025000082952

In [94]: id(c[0])
Out[94]: 140025000084168

In [95]: 
posted @ 2018-12-30 10:20  coder-qi  阅读(387)  评论(0编辑  收藏  举报