当前位置: 首页 > news >正文

Python 引用类型深度解析:从列表赋值到浅拷贝与深拷贝

目录

一、问题引入

二、引用类型

1、(除列表外)常见的可变引用类型

2、引用类型的验证

三、浅拷贝(Shallow Copy)与深拷贝(Deep Copy)

1、浅拷贝

2、深拷贝

四、引用类型、浅拷贝、深拷贝对比表

五、总结与最佳实践


一、问题引入

先看下面这段代码的输出结果:

original_list = [1, 2, 3] new_list = original_list new_list.remove(1) # 从 new_list 中移除元素 1 print(original_list)

输出[2, 3]

分析

  • 原本original_list[1, 2, 3]

  • 执行new_list = original_list后,new_listoriginal_list指向同一个列表对象

  • 因此通过new_list.remove(1)修改列表时,original_list也会同步改变。

  • 这就是引用类型的典型特征:变量存储的是对象的引用(内存地址),赋值操作只是拷贝了引用,而不是对象本身。

二、引用类型

在 Python 中,一切皆对象,变量本质上都是对对象的引用。但通常我们说的“引用类型”特指可变类型(mutable types),因为不可变类型(如整数、字符串、元组)在修改时会创建新对象,不会影响原对象。

1、(除列表外)常见的可变引用类型

类型示例是否可变
字典(dict)d = {'a': 1, 'b': 2}✅ 可变
集合(set)s = {1, 2, 3}✅ 可变
自定义类的实例obj = MyClass()✅ 可变(除非使用不可变字段)
字节数组(bytearray)ba = bytearray(b'hello')✅ 可变
数组模块(array.array)import array; a = array.array('i', [1,2,3])✅ 可变

特别注意

  • 元组tuple虽然不可变,但它包含的元素如果是可变对象,则这些元素仍可被修改(例如元组内嵌列表)。但元组本身的引用不可变。

  • 函数、模块、文件对象等也是引用类型,但通常不直接参与数据拷贝的讨论。

2、引用类型的验证

# 字典示例 d1 = {'x': 10} d2 = d1 d2['x'] = 99 print(d1) # {'x': 99} 被修改 # 集合示例 s1 = {1, 2, 3} s2 = s1 s2.add(4) print(s1) # {1, 2, 3, 4}

三、浅拷贝(Shallow Copy)与深拷贝(Deep Copy)

为了真正复制一个对象(而不是共享引用),我们需要使用拷贝技术。Python 提供了copy模块来实现浅拷贝和深拷贝。

1、浅拷贝

  • 定义:创建一个新对象,但新对象内部的子对象仍然是原对象子对象的引用。

  • 适用场景:对象内部没有嵌套的可变对象,或者你希望共享内层子对象。

  • 方法copy.copy(obj)或类型自身的拷贝方法(如列表的list.copy(),字典的dict.copy())。

浅拷贝示例

import copy original = [1, 2, [3, 4]] shallow = copy.copy(original) # 或者 original.copy() # 修改外层元素(不可变元素,会新建) shallow[0] = 99 print(original) # [1, 2, [3, 4]] 不受影响 # 修改内层列表(可变对象) shallow[2][0] = 999 print(original) # [1, 2, [999, 4]] 原对象被影响

结论:浅拷贝只复制最外层容器,内层嵌套的可变对象仍然共享引用。

2、深拷贝

  • 定义:递归地复制对象及其所有子对象,生成完全独立的副本。

  • 适用场景:需要完全隔离原对象和新对象,修改任意层级都不相互影响。

  • 方法copy.deepcopy(obj)

深拷贝示例

import copy original = [1, 2, [3, 4]] deep = copy.deepcopy(original) deep[2][0] = 888 print(original) # [1, 2, [3, 4]] 完全不受影响

注意:深拷贝可能开销较大,且对于包含循环引用的对象需要特殊处理(deepcopy能处理循环引用)。

四、引用类型、浅拷贝、深拷贝对比表

操作是否创建新容器是否复制内层对象修改内层是否影响原对象
直接赋值=❌ 否❌ 否✅ 是
浅拷贝copy.copy()✅ 是❌ 否(仅复制引用)✅ 是(内层可变时)
深拷贝copy.deepcopy()✅ 是✅ 是(递归)❌ 否

五、总结与最佳实践

  1. 理解引用类型:Python 中列表、字典、集合、类实例等都是可变引用类型。直接赋值不会创建副本,而是让多个变量指向同一对象。

  2. 需要独立副本时

    • 若对象没有嵌套可变结构(如纯数字、字符串、元组的列表),用浅拷贝即可。

    • 若对象包含嵌套列表/字典/自定义对象,应使用深拷贝确保完全隔离。

  3. 性能考量深拷贝比浅拷贝慢且占用更多内存,只在必要时使用。

  4. 不可变类型(int、str、tuple):修改时会创建新对象,因此不存在“意外修改原对象”的问题,但仍需注意不可变容器内嵌套可变对象的情况(如元组内嵌列表)。

回到开头的代码,只需改为浅拷贝或深拷贝即可避免相互影响:

original_list = [1, 2, 3] new_list = original_list.copy() # 浅拷贝(这里没有嵌套,效果等同于深拷贝) new_list.remove(1) print(original_list) # [1, 2, 3] 保持不变
http://www.jsqmd.com/news/605853/

相关文章:

  • MySQL查询核心语法详解
  • 从音频处理到故障诊断:信号频谱分析中的‘混叠’‘栅栏’‘泄漏’问题如何影响你的实际项目?
  • 谷歌Gemma 4实测
  • Fish Speech 1.5镜像CI/CD实践:GitHub Actions自动构建+镜像仓库推送流程
  • 精准靶向学习:AFSS让YOLO训练效率提升 1.43~1.70 倍的奥秘
  • RK3568音频调试避坑指南:播放用I2S1,录音用I2S2,为什么我的dummy_codec会冲突?
  • SerialComProtocol:嵌入式双MCU轻量级串口事件驱动协议
  • Qwen3-14B-Int4-AWQ环境问题排查指南:解决403 Forbidden等常见API访问错误
  • OpenClaw+百川2-13B:个人博客自动化更新系统
  • SEO_本地商家必备的SEO实战方法
  • OpenClaw技能市场挖宝:5个冷门但好用的Qwen2.5-VL-7B专用工具
  • OpenClaw自动化测试方案:Qwen2.5-VL-7B实现UI截图比对与报告生成
  • 把Transformer换成Mamba做多模态特征融合,这几个创新点够你发篇一区了!
  • 别再手动折腾了!用Docker Compose一键部署OpenSPG知识图谱引擎(附客户端配置)
  • OFA视觉蕴含模型优化升级:集成Prometheus监控实现性能可视化
  • TrueLicense避坑指南:SpringBoot项目中License证书的那些常见错误与解决方案
  • OFA视觉问答镜像进阶教程:批量图片处理与结构化答案输出
  • 电商卖家工具:OpenClaw+Qwen3.5-9B-AWQ-4bit自动生成商品详情页
  • 成集云 | 用友U8与聚水潭ERP供应链协同(电商企业实战指南)
  • OpenClaw创意玩法:Qwen3.5-9B-AWQ-4bit生成AI绘画提示词
  • labelme安装在D盘【详细教程】
  • OpenClaw技能扩展:用Kimi-VL-A3B-Thinking打造智能截图分析工具
  • Stable Diffusion v1.5场景应用:电商海报、社交配图,AI绘画实战案例分享
  • Python MCP服务器模板不是“开箱即用”,而是“开箱即审”——等保2.0/ISO27001双认证配置清单首次公开
  • 2026年类风湿诊疗应用白皮书 中医疗法深度剖析 - 优质品牌商家
  • 2026年知名的假发配件/假发配件顺滑液厂家选择推荐 - 行业平台推荐
  • 单细胞转录组分析实战:从Seurat5到Harmony的降维聚类与注释全解析
  • 注意力机制和YOLO算法
  • 千问3.5-35B-A3B-FP8成本优化:OpenClaw长任务token消耗实测
  • 序章 GIMP单骑走天涯