深入理解python浅拷贝和深拷贝(列表,元组,字典,切片)

    xiaoxiao2022-07-04  123

    直接拿代码说话吧 一.浅拷贝 1.1赋值拷贝

    # 关于浅拷贝 # 浅拷贝的几种 # 1 赋值拷贝 # 赋值拷贝 只拷贝了对象的引用,修改拷贝对象的值也会对原来的值有影响 a = [1,2,3] b = a b.append(4) print(a) print(b) print(id(a)) print(id(b)) """ [1, 2, 3, 4] [1, 2, 3, 4] 1962638078088 1962638078088 """

    1.2赋值拷贝的一些问题

    import copy # 浅拷贝 # 用copy模块.copy进行拷贝 只是拷贝了一个对象的顶层,里面的东西仍然拷贝的是引用 a = [1,2,3] b = copy.copy(a) # 在b中新增了一个元素 # 为什么不影响呢? """ a中有三个基本数据类型,b拷贝了a的最外层分配了一个新的空间。 里层内容拷贝的是引用,b总新增了一个基本数据与a没有关联,因为没有对a中数据进行修改 """ b.append(4) print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) """ [1, 2, 3] [1, 2, 3, 4] 2423525240968 2423535521288 1467575312 1467575312 """

    1.3.1copy调用copy模块进行浅拷贝

    import copy # 浅拷贝 # 用copy模块.copy进行拷贝 只是拷贝了一个对象的顶层,里面的东西仍然拷贝的是引用 a = [1,2,3] b = copy.copy(a) # 我们修改b中的值a中的值会受到影响吗? b[0] = 5 print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) """ [1, 2, 3] [5, 2, 3] 2523524133000 2523543491016 1467575312 1467575440 """ # 发现没有受到影响,因为通过赋值拷贝传递了引用,此时b[0]指向值为5的对象,与a无关

    1.3.2

    import copy # 浅拷贝 a = [[1,2],[3,4]] b = copy.copy(a) b[0] = [1,2,3]# 与上同理不会改变原来的值 print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) ''' [[1, 2], [3, 4]] [[1, 2, 3], [3, 4]] 3235770114376 3235761245704 3235750965384 3235770264072 '''

    1.4copy调用copy模块进行浅拷贝

    import copy # 浅拷贝 只是考虑了顶层的列表(分配了新的存储空间) # 列表里的东西都拷贝的是引用 c = [1,2] d = [3,4] a = [c,d] b = copy.copy(a) c.append(5) print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) ''' [[1, 2, 5], [3, 4]] [[1, 2, 5], [3, 4]] 1663393898696 1663385009672 1663374684296 1663374684296 '''

    1.5对切片的拷贝

    import copy # 列表的切片赋值是浅拷贝还是深拷贝? c = [1,2] d = [3,4] a = [c,d] b = a[:] c.append(3) print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) ''' [[1, 2, 3], [3, 4]] [[1, 2, 3], [3, 4]] 1696674324872 1696666469640 1696655306888 1696655306888 ''' # 发现是浅拷贝,对新列表的操作也会对原来列表影响 # 在处理数据时,要考虑到对原数据的污染

    二 深拷贝 2.1 用copy模块的deepcopy方法列表的深拷贝

    import copy import copy # 深拷贝 是递归拷贝,它不会拷贝数据的引用 而是重新分配了存储空间 a = [[1,2],[3,4]] b = copy.deepcopy(a) b[0] = [1,2,3] # 深拷贝不会改变原来的值 print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) ''' [[1, 2], [3, 4]] [[1, 2, 3], [3, 4]] 2072156288456 2072168263112 2072168224904 2072156288584 #发现id值不相同,说明重新分配了存储空间 '''

    2.2 用copy模块的copy方法字典的拷贝

    import copy # 字典的浅拷贝 a = {'age': 27,'name': 'zhangsan','list_age' : [12,24]} b = copy.copy(a) b['age'] = 100 # 赋值拷贝会影响 b['list_age'].append(23) # 对字典的浅拷贝内部仍然是拷贝的引用 print(a) print(b) print(id(a)) print(id(b)) 2384697861968 2384697861248 import copy # 字典的深拷贝 a = {'age': 27,'name': 'zhangsan','list_age' : [12,24]} b = copy.deepcopy(a) b['age'] = 100 # 赋值拷贝不会影响 b['list_age'].append(23) print(a) print(b) print(id(a)) print(id(b))

    三 深拷贝和浅拷贝之间的比较

    import copy a = [11,22] b = (a,) c = [b, ] d = copy.copy(c) a.append(33) print(c) print(d) print(id(c)) print(id(d)) # 浅拷贝只是拷贝了最外层,里层拷贝了引用 ''' [([11, 22, 33],)] [([11, 22, 33],)] 2866062314824 2866071179528 import copy a = [11,22] b = (a,) c = [b, ] d = copy.deepcopy(c) a.append(33) print(c) print(d) print(id(c)) print(id(d)) # 深拷贝只是拷贝了都重新分配了存储空间进行了拷贝 ''' [([11, 22, 33],)] [([11, 22],)] 1970627436808 1970627350600

    四 小结 在copy.copy方法中浅拷贝只是拷贝了顶层框架,并给顶层重新分配了存储空间,其他部分仍然拷贝的是引用 在copy.deepcopy方法中深拷贝,对所有东西进行递归拷贝,并全部重新分配了存储空间 赋值拷贝拷贝的是引用,拷贝数据和源数据的地址是相同的 对列表的切片后赋值拷贝的也是引用,对列表进行操作时要注意对原数据的污染

    最新回复(0)