流畅的python,Python可视化网站
深复制与浅复制早就有所耳闻,今天发现没有进行相关笔记。这里简单写下,不做深入探讨。
默认为浅复制
浅复制就是仅复制了最外层的引用,而对内部引用不做复制操作;对于不可变元素,这是很好的,减少了内存消耗。然而当内部元素是可变的,就会产生非预期的事情。Python中默认使用浅复制,例如列表中可以采用[:] 与 list() 构造进行复制操作。以下是一段代码,及其内存情况展示,可方便理解,面对不同元素对象操作时的异同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| l1 = [3, [66,55,44]
l2 = list(l1) l1.append(100) l1[1].remove(55) print("l1 ,", l1 ) print("l2 ," ,l2)
l2[1] += [33,22] l2[2] += (10 ,11) print("l1 ,", l1 ) print("l2 ," ,l2)
|
(1)可以看到上图中通过浅复制,l1,l2指向了不同的对象,而对象内部元素的引用并没有变化。
(2)可以看到在对l1中的列表元素进行操作直接影响了l2中列表元素的情况,这当然是由于其内部列表元素指向对象一致,并且列表是可变元素。 可变元素就说明其支持原地修改。
(3)同理,l2中对列表元素的修改,也会影响到l1的内部情况。
(4)需要注意,对l2的tuple元素进行修改操作时,l1,l2不再指向同一tuple,这是由于元组本身不支持就地修改操作,其构建了一个新的元组对象并返回给了l2[2]的位置。
如何进行深浅拷贝
Python提供了copy库方便提供了copy()与deepcopy()方法,很方便。使用方式展示:
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
| """ >>> import copy >>> bus1 = Bus(['Alice', 'Bill', 'Claire', 'David']) >>> bus2 = copy.copy(bus1) >>> bus3 = copy.deepcopy(bus1) >>> bus1.drop('Bill') >>> bus2.passengers ['Alice', 'Claire', 'David'] >>> bus3.passengers ['Alice', 'Bill', 'Claire', 'David']
"""
class Bus:
def __init__(self, passengers=None): if passengers is None: self.passengers = [] else: self.passengers = list(passengers)
def pick(self, name): self.passengers.append(name)
def drop(self, name): self.passengers.remove(name)
|
循环引用问题
深拷贝并没有那么简单,例如遇到循环引用时,岂不是会无限copy。不过这不用担心,Python自带的copy库可以记住已经copy过的对象。大胆用。