Python 高阶内容:深拷贝与浅拷贝揭秘复制的“玄学”
文章目录
在 Python 中,复制操作并不是简单地将对象内容重新创建,而是存在着深拷贝(Deep Copy)和浅拷贝(Shallow Copy)两种方式。浅拷贝只是复制对象本身,不包括内部嵌套的子对象;如果内部对象被修改,原始对象也会受到影响。而深拷贝则是递归地复制对象及其所有子对象,生成一个完全独立的副本,确保原对象和副本之间互不影响。浅拷贝通常通过对象的 .copy()
方法或切片操作实现,适用于对象中不包含可变子对象或希望共享子对象的情况。而深拷贝则需要使用 copy
模块中的 deepcopy()
函数,适用于需要完全独立的副本,避免任何联动修改的场景。
掌握这两种拷贝方式的区别与应用,可以帮助开发者在不同场景下更好地管理数据和内存。本文通过实例详解了深拷贝与浅拷贝的不同特点及适用场景,帮助你轻松理解这一看似“玄学”的知识点。
一 copy 数据
复制本质是复制地址和复制值。
示例一
l = [1, 2, 3]
_l = l.copy()
_l[0] = -1
print(_l)
print(l)
运行的之后
[-1, 2, 3]
[1, 2, 3]
示例二
l = [[1], [2], 3]
_l = l.copy()
_l[0][0] = -1
print(_l)
print(l)
运行的之后
[[-1], [2], 3]
[[-1], [2], 3]
运行后,发现,源列表居然变了,再来看一个实例。
audio = File("mp3")
file = File("txt")
l = [audio, file]
_l = l.copy()
_l[0].name = "mp4"
print(audio.name)
# 运行之后 "mp4"
运行之后源列表是 mp3 的,怎么被复制后的列表改变成了 mp4 。
二 深拷贝与浅拷贝
Python 中复制,有两种方式,一种是深拷贝,一种是浅拷贝。
深拷贝是 Deep Copy,浅拷贝是 Shallow Copy,Deep copy 就是我们通常意义上的复制,把东西全部再造了一遍,彻底成为了两个独立的个体。 而Shallow Copy, 其实也有一点影子拷贝的意思,我复制出来的是你的一个影子,一个投影成像。 所以真实的实体是没有被复制的,我只复制了这个实体的一个投影而已。这里有点绕。划重点 Python 对数值字符的复制是直接复制的值
,浅复制的优势就是快。复制是需要内存和时间的,因为浅复制没有真正复制,所以并不需要耗多少内存和时间。
那如何拷贝出互不影响的实例列表呢?对存放实例的列表做 Deep Copy 深拷贝。
from copy import deepcopy
l = [[1], [2], 3]
_l = deepcopy(l)
_l[0][0] = -1
print(_l)
print(l)
三 copy 对比
基本概念对比
比较项 | 浅拷贝(Shallow Copy) | 深拷贝(Deep Copy) |
---|---|---|
定义 | 仅复制对象本身,内部的子对象仍然引用原始对象的子对象 | 递归地复制对象及其所有子对象,生成全新的副本 |
对象关系 | 新对象与原对象共享可变的子对象 | 新对象与原对象完全独立,修改互不影响 |
适用场景 | 对象中不包含可变的子对象,或希望共享子对象的情况 | 需要完全独立的副本,避免任何联动修改的情况 |
实现方式对比
比较项 | 浅拷贝实现方法 | 深拷贝实现方法 |
---|---|---|
内置方法 | 使用对象的 .copy() 方法 | 无 |
copy 模块 | copy.copy(obj) | copy.deepcopy(obj) |
列表特有 | 切片操作:new_list = original_list[:] | 无 |
示例代码 | shallow_copied_list = copy.copy(original_list) 或 shallow_copied_list = original_list[:] | deep_copied_list = copy.deepcopy(original_list) |
四 完整代码示例
# This is a sample Python script.
# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint.
# 我的确复制了呀, 复制数值
# 复制本质是复制地址和复制值
l = [1, 2, 3]
_l = l.copy()
_l[0] = -1
print(_l)
print(l)
# 看看这个示例
l = [[1], [2], 3]
_l = l.copy()
_l[0][0] = -1
print(_l)
print(l)
# 运行后,发现,源列表居然变了,再来看一个实例
audio = File("mp3")
file = File("txt")
l = [audio, file]
_l = l.copy()
_l[0].name = "mp4"
print(audio.name) # "mp4"
# 源列表是 mp3 的,怎么被复制后的列表改变成了 mp4
# Python 中复制,有两种方式,一种是深拷贝,一种是浅拷贝。
# 深拷贝与浅拷贝
# 深拷贝是 Deep Copy,浅拷贝是 Shallow Copy
# Deep copy 就是我们通常意义上的复制,把东西全部再造了一遍,彻底成为了两个独立的个体。 而
# Shallow Copy, 其实也有一点影子拷贝的意思,我复制出来的是你的一个影子,一个投影成像。 所以真实的实体是没有被复制的,我只复制了这个实体的一个投影而已。
# Python 对数值字符的复制,直接是复制的值
# 对存放实例的列表做 Deep Copy 深拷贝
from copy import deepcopy
l = [[1], [2], 3]
_l = deepcopy(l)
_l[0][0] = -1
print(_l)
print(l)
class File:
def __init__(self, name):
self.name = name
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('复制的"玄学"')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。
Hi, 复制的"玄学"
[-1, 2, 3]
[1, 2, 3]
[[-1], [2], 3]
[[-1], [2], 3]
mp4
[[-1], [2], 3]
[[1], [2], 3]
五 源码地址
代码地址:
国内看 Gitee 之 复制的"玄学".py
国外看 GitHub 之 复制的"玄学".py
引用 莫烦 Python
标签:Copy,Python,对象,复制,print,拷贝,copy,高阶 From: https://blog.csdn.net/u014394049/article/details/142410985