当前位置:   article > 正文

Python之旅——列表深浅拷贝_python深浅拷贝的列表嵌套列表

python深浅拷贝的列表嵌套列表

列表深浅拷贝

将列表中的值,拷贝到的容器。

先思考一下,采用下列方式,是否能达到拷贝列表的目的?

nums = [1, 2, 3]
copied_nums = nums

print(f"nums={nums}")
print(f"copied_nums={copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5

代码输出:

nums=[1, 2, 3]
copied_nums=[1, 2, 3]
  • 1
  • 2

上述仅仅是,将copied_nums变量与nums变量都指向了相同的列表对象。如若不信,请查看下列代码:

nums = [1, 2, 3]
copied_nums = nums

copied_nums[2] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码输出:

nums addr[0x27968a65208], val:[1, 2, 1010]
copied_nums addr[0x27968a65208], val:[1, 2, 1010]
  • 1
  • 2

普通列表拷贝

  • list对象构造
  • list生成表达式
  • 使用copy库

list对象构造

nums = [1, 2, 3]
copied_nums = list(nums)    # list 对象构造方式

copied_nums[2] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码输出:

nums addr[0x1d53e2f5208], val:[1, 2, 3]
copied_nums addr[0x1d540189a88], val:[1, 2, 1010]
  • 1
  • 2

list生成表达式

nums = [1, 2, 3]
copied_nums = [num for num in nums]     # list生成表达式

copied_nums[2] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码输出:

nums addr[0x14dd8165208], val:[1, 2, 3]
copied_nums addr[0x14dd8165408], val:[1, 2, 1010]
  • 1
  • 2

copy库

import copy

nums = [1, 2, 3]
copied_nums = copy.copy(nums)     # copy库拷贝

copied_nums[2] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码输出:

nums addr[0x2329f3143c8], val:[1, 2, 3]
copied_nums addr[0x2329f2f9ac8], val:[1, 2, 1010]
  • 1
  • 2

嵌套列表拷贝

若列表中嵌套列表,上述三种方式(浅拷贝)将不再可用。采用list对象构造方式,可自行尝试上述介绍的其他方式:

nums = [1, 2, 3, [4, 5, 6]]
copied_nums = list(nums)     # list 对象构造方式

copied_nums[3][1] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

代码输出:

nums addr[0x29ec7dc5408], val:[1, 2, 3, [4, 1010, 6]]
copied_nums addr[0x29ec8149b48], val:[1, 2, 3, [4, 1010, 6]]
  • 1
  • 2

当然,可采用2层的for语句的方式,实现拷贝嵌套一层的列表。但是,如果是嵌套层级太深,那就需要太多的for语句,同时还依赖于每个列表成员的数据类型。

递归方式

def deep_copy_list(nums):
    '''
    仅支持int的列表成员和嵌套列表的拷贝
    '''
    items = []
    for num in nums:
        if isinstance(num, int):
            items.append(num)
        else:
            items.append(deep_copy_list(num))
    return items

nums = [1, 2, 3, [4, 5, 6]]
copied_nums = deep_copy_list(nums)     # 递归调用拷贝函数

copied_nums[3][1] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

代码输出:

nums addr[0x22f87b753c8], val:[1, 2, 3, [4, 5, 6]]
copied_nums addr[0x22f87ef95c8], val:[1, 2, 3, [4, 1010, 6]]
  • 1
  • 2

使用库函数

使用自定义的拷贝函数,需要比较完善的考虑,支持各种数据类型和列表的嵌套。不过,python中有提供现成的深拷贝库函数:

import copy

nums = [1, 2, 3, [4, 5, 6]]
copied_nums = copy.deepcopy(nums) 

copied_nums[3][1] = 1010

print(f"nums addr[0x{id(nums):x}], val:{nums}")
print(f"copied_nums addr[0x{id(copied_nums):x}], val:{copied_nums}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码输出:

nums addr[0x15cad719c48], val:[1, 2, 3, [4, 5, 6]]
copied_nums addr[0x15cad719c88], val:[1, 2, 3, [4, 1010, 6]]
  • 1
  • 2

总结

  • 浅拷贝:仅拷贝集合最外层的成员值,和嵌套的集合对象的引用,到新的集合对象。
  • 深拷贝:嵌套集合中的所有对象都将被拷贝到新的集合对象。

注:
一般情况下,仅用到浅拷贝;若使用到深拷贝,那表明程序框架需要再考虑。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/602114
推荐阅读
相关标签
  

闽ICP备14008679号