• Python 列表切片陷阱:引用、复制与深复制


    大家早好、午好、晚好吖 ❤ ~欢迎光临本文章

    如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码

    Python 列表的切片和赋值操作很基础,之前也遇到过一些坑,

    但今天刷 Codewars 时发现了一个更大的坑,故在此记录。

    Python 列表赋值:复制“值”还是“引用”?

    很多入门 Python 的人会犯这样一个错误:在赋值操作=中搞不清是赋了“值”还是“引用”。

    比如:

    a = [1, 2, 3]
    b = a
    b[0] = 10  # 更改列表 b 的第一个元素,但 a 现在也被更改为了 [10, 2, 3]
    
    • 1
    • 2
    • 3

    他可能只想改变列表b,但实际上这样也会改变列表a。

    因为b实际上是列表a的另一个引用,a和b是同一个对象,id(a) == id(b),所以更改b也会更改a。

    这个应该大部分人都知道。

    所以正确的代码应该使用切片来进行列表的复制:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:702813599
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    a = [1, 2, 3]
    b = a[:]  # 使用切片进行列表复制
    b[0] = 10  # 此时 a 和 b 是两个不同的对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    二维列表引发的思考:列表的本质

    好的,现在我们确定切片能够进行列表的复制。

    那我们就能心安理得地改动新的列表了吗?

    请看二维列表(二维数组):

    a = [[1, 2, 3], [4, 5, 6]]
    b = a[:]
    b[0][0] = 10
    
    • 1
    • 2
    • 3

    此时,a还是被改动了!

    原因是,虽然id(a) == id(b)为False,a和b确实不是同一个对象。

    但它们的元素都是同一个对象——id(a[0]) == id(b[0])id(a[1]) == id(b[1])。因为列表里存储的是对象的引用!

    列表 list 终究只是个容器。

    就像 tuple 本身是 immutable (不可变)的,但它只是容器,它可以存储一个可变对象,因此呈现出一种可以被改动的“假象”。

    例如:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:702813599
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    >>> a = ([1],)
    >>> a[0][0] = 2
    >>> a
    ([2],)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    所以容器和它存储的对象不能混为一谈。

    所以对于这种二维列表,想要进行完全的复制,请直接使用copy.deepcopy()深度复制。

    如果只想复制一部分(切片),那可以先复制再切片:

    >>> import copy
    >>> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    >>> b = copy.deepcopy(a)[1:]
    >>> b[0][0] = 100
    
    >>> a
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    >>> b
    [[100, 5, 6], [7, 8, 9]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    此时修改b没有影响到a。

    尾语

    好了,今天的分享就差不多到这里了!

    对下一篇大家想看什么,可在评论区留言哦!看到我会更新哒(ง •_•)ง

    喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!

    最后,宣传一下呀~👇👇👇 更多源码、资料、素材、解答、交流 皆点击下方名片获取呀👇👇👇

  • 相关阅读:
    Volatility2工具mimiktz脚本
    简易根文件系统构建实验及过程详解
    为什么 think-cell 图表中的标签显示为白色矩形?
    cpp中的函数重载
    C++ Reference: Standard C++ Library reference: C Library: cwchar: wcspbrk
    结构化技能——特征筛选
    Kubernetes弃用Docker?别误解!这份理论实战都具备的手册还得继续学习呀
    Linux系统编程:进程part_1
    编码数据未来:Python数据科学的现代工具箱
    基于 Python 解析 XML 文件并将数据存储到 MongoDB 数据库
  • 原文地址:https://blog.csdn.net/weixin_62853513/article/details/133826483