Python中copy() 函数浅拷贝与深拷贝示例详解

 更新时间:2025年11月14日 10:46:36   作者:Geoking.  
Python的copy()函数是copy模块提供的一个用于创建对象浅拷贝的工具,这篇文章主要介绍了Python中copy()函数浅拷贝与深拷贝的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在 Python 编程中,对象的拷贝(复制) 是一个常见又容易被忽视的概念。很多初学者在使用 copy() 时,常常会遇到修改一个对象导致另一个对象也被改变的“奇怪现象”。本文将深入理解 Python 的 copy() 函数、浅拷贝与深拷贝的区别,并通过示例让你彻底搞清楚它们的原理。

一、为什么需要拷贝对象?

当你在 Python 中使用赋值语句时,例如:

a = [1, 2, 3]
b = a

此时,ab指向同一个对象。这意味着修改 b 也会影响 a

b.append(4)
print(a)  # 输出:[1, 2, 3, 4]
print(b)  # 输出:[1, 2, 3, 4]

这往往不是我们想要的结果。

如果希望创建一个“新的对象”,而不是仅仅复制引用,这时就需要用到 拷贝函数

二、copy模块简介

Python 标准库提供了一个专门用于复制对象的模块:copy
该模块中有两个重要函数:

  • copy.copy(x) —— 执行 浅拷贝
  • copy.deepcopy(x) —— 执行 深拷贝

我们先来看看浅拷贝。

三、浅拷贝 (copy.copy())

浅拷贝会创建一个新的对象,但不会递归地复制内部的可变对象

示例:

import copy

list_a = [1, [2, 3], 4]
list_b = copy.copy(list_a)

print(list_a == list_b)  # True,内容相同
print(list_a is list_b)  # False,指向不同对象

修改外层列表时,互不影响:

list_b.append(5)
print(list_a)  # [1, [2, 3], 4]
print(list_b)  # [1, [2, 3], 4, 5]

但修改内部的可变对象时,浅拷贝仍然会“联动”:

list_b[1].append(99)
print(list_a)  # [1, [2, 3, 99], 4]
print(list_b)  # [1, [2, 3, 99], 4, 5]

✅ 结论:浅拷贝只复制最外层容器,内部元素仍然是原对象的引用。

四、深拷贝 (copy.deepcopy())

深拷贝则会递归地复制所有对象,生成完全独立的一份副本。

import copy

list_a = [1, [2, 3], 4]
list_b = copy.deepcopy(list_a)

list_b[1].append(99)

print(list_a)  # [1, [2, 3], 4]
print(list_b)  # [1, [2, 3, 99], 4]

✅ 结论:深拷贝创建了一个完全独立的对象副本,任何修改都不会相互影响。

五、不同数据类型的拷贝行为

数据类型浅拷贝结果深拷贝结果
int, float, str, bool不可变对象,直接共享相同效果
list, dict, set复制容器,但内部引用相同完全独立副本
tuple如果内部包含可变对象,浅拷贝仍共享引用内部对象独立
自定义类对象可自定义 __copy__ / __deepcopy__ 方法可完全控制复制逻辑

六、自定义类的拷贝行为

Python 允许开发者通过实现特殊方法 __copy____deepcopy__ 来控制类的复制方式。

示例:

import copy

class Person:
    def __init__(self, name, hobbies):
        self.name = name
        self.hobbies = hobbies

    def __copy__(self):
        print("调用浅拷贝")
        return type(self)(self.name, self.hobbies)

    def __deepcopy__(self, memo):
        print("调用深拷贝")
        new_person = type(self)(self.name, copy.deepcopy(self.hobbies, memo))
        return new_person

p1 = Person("Alice", ["reading", "coding"])
p2 = copy.copy(p1)
p3 = copy.deepcopy(p1)

七、常见坑点总结

  1. 浅拷贝不会递归复制内部对象
a = [[1, 2], [3, 4]]
b = copy.copy(a)
b[0].append(99)
print(a)  # [[1, 2, 99], [3, 4]]
  1. 不可变对象(如 int, str, tuple)无需担心浅拷贝问题
a = (1, 2, 3)
b = copy.copy(a)
print(a is b)  # True
  1. 深拷贝性能开销较大
    深拷贝会递归复制所有内容,对于嵌套层级深或对象复杂的结构,速度会明显变慢。
    如果不需要完全隔离,优先使用浅拷贝。

八、总结

概念是否创建新对象是否递归复制适用场景
赋值(=两变量共享同一对象
浅拷贝(copy.copy()仅需复制一层结构
深拷贝(copy.deepcopy()需要完全独立的副本

九、实践建议

  • 若仅修改外层容器,用 copy.copy() 即可。
  • 若修改嵌套结构(如列表中包含列表),用 copy.deepcopy()
  • 若对象复杂,考虑自行实现 __copy____deepcopy__,以提升性能与控制力。

浅拷贝复制外壳,深拷贝复制灵魂。

到此这篇关于Python中copy() 函数浅拷贝与深拷贝的文章就介绍到这了,更多相关Python中copy()函数浅拷贝深拷贝内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • drf序列化器serializer的具体使用

    drf序列化器serializer的具体使用

    本文主要介绍了drf序列化器serializer的具体使用,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • numpy中索引和切片详解

    numpy中索引和切片详解

    这篇文章主要介绍了numpy中索引和切片详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Django实现随机图形验证码的示例

    Django实现随机图形验证码的示例

    这篇文章主要介绍了Django实现随机图形验证码的示例,帮助大家更好的学习和使用django框架,感兴趣的朋友可以了解下
    2020-10-10
  • Python编程实现粒子群算法(PSO)详解

    Python编程实现粒子群算法(PSO)详解

    这篇文章主要介绍了Python编程实现粒子群算法(PSO)详解,涉及粒子群算法的原理,过程,以及实现代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Python字符串split及rsplit方法原理详解

    Python字符串split及rsplit方法原理详解

    这篇文章主要介绍了Python字符串split及rsplit方法原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • python实现自动重启本程序的方法

    python实现自动重启本程序的方法

    这篇文章主要介绍了python实现自动重启本程序的方法,涉及Python进程操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • GPU版本安装Pytorch的最新方法步骤

    GPU版本安装Pytorch的最新方法步骤

    最近深度学习需要用GPU版本的pytorch来加速运算,所以下面这篇文章主要给大家介绍了关于GPU版本安装Pytorch的最新方法步骤,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • python实现俄罗斯方块小游戏

    python实现俄罗斯方块小游戏

    这篇文章主要为大家详细介绍了python实现俄罗斯方块小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • Pyqt5 实现多线程文件搜索的案例

    Pyqt5 实现多线程文件搜索的案例

    这篇文章主要介绍了Pyqt5 实现多线程文件搜索的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Pytorch损失函数torch.nn.NLLLoss()的使用

    Pytorch损失函数torch.nn.NLLLoss()的使用

    这篇文章主要介绍了Pytorch损失函数torch.nn.NLLLoss()的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02

最新评论