python快速入门学习笔记(进阶篇)十七:浅拷贝 与 深拷贝

  • 原创
  • 作者:程序员三丰
  • 发布时间:2026-04-01 09:45
  • 浏览量:14
python入门第十七课,主要是学习了浅拷贝与深拷贝:浅拷贝只复制最外层容器,内层元素共享原对象引用;深拷贝递归复制所有层级,生成完全独立的副本。

为什么要拷贝?

在 Python 中,会存在如下情况:

  • 例如复制语句:b = a,只是让b指向和a一样的对象。
  • 如果ab指向的是一个可变对象,那通过修改b后,再通过a访问到的数据也是变化后的。

但是,很多时候,我们不希望是这样的,而是希望ab修改任何一个,都不影响彼此,此时就需要用到拷贝。

直接赋值

在如下代码中:nums2 = nums1不是复制,是两个变量指向同一个列表,并且修改任何一个,都会影响另一个。

nums1 = [10, 20, 30, 40]
nums2 = nums1
nums2[3] = 90
print(nums1) # [10, 20, 30, 90]
print(nums2) # [10, 20, 30, 90]

# 打印内存地址: 2346908951744 2346908951744 True 它们的内存地址是同一个地址
print(id(nums1), id(nums2), id(nums1) == id(nums2))

浅拷贝 copy

浅拷贝会创建一个新的外层容器,但内部的元素仍然引用原来的对象。请看下面的测试代码:

import copy

nums3 = [10, 20, 30, 40]
nums4 = copy.copy(nums3)
nums4[3] = 90
print(nums3) # [10, 20, 30, 40]
print(nums4) # [10, 20, 30, 90]
# 打印内存地址:2032469602560 2032470409088 False 它们的内存地址不是同一个地址了
print(id(nums3), id(nums4), id(nums3) == id(nums4))

浅拷贝存在的问题是:嵌套数据仍然是共享的,修改嵌套数据会相互影响。测试代码如下:

import copy

nums5 = [10, 20, 30, [40, 50]]
nums6 = copy.copy(nums5)
nums6[2] = 300
nums6[3][1] = 90
print(nums5) # [10, 20, 30, [40, 90]]
print(nums6) # [10, 20, 300, [40, 90]]
# 打印内存地址:2032469602560 2032470409088 False 它们的内存地址不是同一个地址了,但是嵌套的数据还是影响了
print(id(nums5), id(nums6), id(nums6) == id(nums5))

如何解决这个问题呢?请看下面的深拷贝。

深拷贝 deepcopy

创建一个新的外层容器,同时对内部所有【可变对象】进行递归复制(不可变对象不复制,继续引用)。

import copy

nums7 = [10, 20, 30, [40, 50]]
nums8 = copy.deepcopy(nums7)
nums8[2] = 300
nums8[3][1] = 90
print(nums7) # [10, 20, 30, [40, 50]]
print(nums8) # [10, 20, 300, [40, 90]]
# 打印内存地址:2383166804288 2383166804352 False 它们的内存地址不是同一个地址了,但是嵌套的数据也不影响
print(id(nums7), id(nums8), id(nums8) == id(nums7))

特点:

❏ 深拷贝可以彻底消除拷贝前后数据之间的相互影响。

❏ 深拷贝遇到【不可变对象】不会复制,会直接引用。

注意点:

❏ 深拷贝只复制可变对象,不可变对象会直接引用。测试代码如下:

import copy

aa = 6
# aa是不可变对象,即便调用deepcopy也不会深拷贝,会直接引用
cc = copy.deepcopy(aa)
print(aa, cc) # 6 6
# 2346908951744 2346908951744 True 它们的内存地址是同一个地址
print(id(aa), id(cc), id(cc) == id(aa))

总结

赋值、浅拷贝、深拷贝在实际开发中要根据具体业务场景选择合适方式使用,不能滥用,可能会造成数据异常。

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://mp.51blog.xyz/article/119.html

文章归档

推荐文章

buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3 three.js 微信支付 PHP全栈开发 Python AI 人工智能 AI生成 工作经验 实战笔记