【Python】通过现象和本质理解python赋值、浅拷贝、深拷贝

文章讲述了Python中赋值、浅拷贝和深拷贝的区别,主要通过元组和列表实例分析。对于不可变数据,浅拷贝和深拷贝ID不同但数据一致;可变数据中,浅拷贝ID不同且数据一致,深拷贝ID和数据独立。通过改变1级和2级数据展示了不同操作的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。



前言

我理解中,深拷贝和浅拷贝是Python数据类型可变和不可变的延伸,主要是处理组合数据类型:元组、列表、集合、字典。我们这里主要以元组和列表为例记性展示。

  1. 对于1级不可变数据类型,浅拷贝和深拷贝id地址不同,拷贝数据一致不改变。
  2. 对于1级可变数据类型,浅拷贝和深拷贝id地址不同,拷贝数据一致不改变。

一、看问题本质

1.认识赋值、浅拷贝、深拷贝

示例代码

import copy

a = [1, 2]
b = [3, 4]
c = (a, b)
d = [a, b]

print('---1层不可变,2层可变---')
赋值_c = c
浅拷贝_c = copy.copy(c)
深拷贝_c = copy.deepcopy(c)
print('a',id(a))
print('b',id(b))
print('c',id(c))
print('赋值_c',id(赋值_c))
print('浅拷贝_c',id(浅拷贝_c))
print('深拷贝_c',id(深拷贝_c))

print('---1层可变,2层可变---')
赋值_d = d
浅拷贝_d= copy.copy(d)
深拷贝_d = copy.deepcopy(d)
print('a',id(a))
print('b',id(b))
print('d',id(d))
print('赋值_d',id(赋值_d))
print('浅拷贝_d',id(浅拷贝_d))
print('深拷贝_d',id(深拷贝_d))

示例结果
在这里插入图片描述

通过示例结果,可以看到对于不可变数据类型,赋值和浅拷贝是一样的,指向的id没有发生变化。深拷贝id发生变化;对于可变数据类型,赋值时id未发生变化,浅拷贝和深拷贝的id均发生变化。

二.看问题现象

通过改变可变类型,我们查看赋值、浅拷贝、深拷贝的具体变化。上一步中我们使用了1级数据和2级数据,这里我们就通过改变他们来试验。

1.改变1级数据,这里要改变d

示例代码

import copy


a = [1, 2]
b = [3, 4]
c = (a, b)
d = [a, b]

# 1层不可变,2层可变
print('---1层不可变,2层可变---')
赋值_c = c
浅拷贝_c = copy.copy(c)
深拷贝_c = copy.deepcopy(c)
print('a',id(a))
print('b',id(b))
print('c',id(c))
print('赋值_c',id(赋值_c))
print('浅拷贝_c',id(浅拷贝_c))
print('深拷贝_c',id(深拷贝_c))

print('---1层可变,2层可变---')
赋值_d = d
浅拷贝_d= copy.copy(d)
深拷贝_d = copy.deepcopy(d)
print('a',id(a))
print('b',id(b))
print('d',id(d))
print('赋值_d',id(赋值_d))
print('浅拷贝_d',id(浅拷贝_d))
print('深拷贝_d',id(深拷贝_d))

d.append(10)
print('****改变1级数据,d中增加元素')
print('---1层不可变,2层可变---')
print('a',a)
print('b',b)
print('c',c)
print('赋值_c',赋值_c)
print('浅拷贝_c',浅拷贝_c)
print('深拷贝_c',深拷贝_c)
print('---1层可变,2层可变---')
print('a',a)
print('b',b)
print('d',d)
print('赋值_d',赋值_d)
print('浅拷贝_d',浅拷贝_d)
print('深拷贝_d',深拷贝_d)

示例结果
在这里插入图片描述

这个示例中不需要看c,我们直接看d的相关数据,通过示例结果可以看出,对于1级可变数据,浅拷贝和深拷贝id不同但是结果一样,对于1级可变数据类型,浅拷贝和深拷贝id地址不同,拷贝数据一致不改变

2.改变2级数据,这里改变a或者b

示例代码

import copy


a = [1, 2]
b = [3, 4]
c = (a, b)
d = [a, b]

# 1层不可变,2层可变
print('---1层不可变,2层可变---')
赋值_c = c
浅拷贝_c = copy.copy(c)
深拷贝_c = copy.deepcopy(c)
print('a',id(a))
print('b',id(b))
print('c',id(c))
print('赋值_c',id(赋值_c))
print('浅拷贝_c',id(浅拷贝_c))
print('深拷贝_c',id(深拷贝_c))

print('---1层可变,2层可变---')
赋值_d = d
浅拷贝_d= copy.copy(d)
深拷贝_d = copy.deepcopy(d)
print('a',id(a))
print('b',id(b))
print('d',id(d))
print('赋值_d',id(赋值_d))
print('浅拷贝_d',id(浅拷贝_d))
print('深拷贝_d',id(深拷贝_d))


a.append(10)
print('****改变2级数据,a中增加元素')
print('---1层不可变,2层可变---')
print('a',a)
print('b',b)
print('c',c)
print('赋值_c',赋值_c)
print('浅拷贝_c',浅拷贝_c)
print('深拷贝_c',深拷贝_c)
print('---1层可变,2层可变---')
print('a',a)
print('b',b)
print('d',d)
print('赋值_d',赋值_d)
print('浅拷贝_d',浅拷贝_d)
print('深拷贝_d',深拷贝_d)

示例结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/87e8995b7b0e4f2db273c01ba1c76547.png

通过示例结果可以看出,对于一层不可变二层可变的数据,赋值和浅拷贝id地址相同数据一致均改变,深拷贝与其他两项id不同、数据不一致未改变;对于一层可变二层可变的数据,赋值、浅拷贝、深拷贝id地址均不同,赋值和浅拷贝数据一致均改变,深拷贝数据未改变。

<think>好的,我现在要回答用户关于Python赋值深拷贝还是浅拷贝的问题。首先,我需要确认自己对这两个概念的理解是否正确。浅拷贝(Shallow Copy)会创建一个新对象,然后插入原对象中元素的引用。也就是说,如果原对象中的元素是可变的,修改这些元素会影响拷贝后的对象。而深拷贝(Deep Copy)则是完全复制原对象及其所有子对象,生成一个完全独立的新对象,两者互不影响。 接下来,用户的问题是关于Python中的赋值操作属于哪一种。根据我的知识,普通的赋值操作(如使用等号=)实际上并不会创建新对象,而只是将变量名指向同一个对象。这时候,变量名相当于原对象的一个别名,两者指向同一块内存地址。因此,无论是可变对象(如列表、字典)还是不可变对象(如整数、字符串),通过赋值操作后的变量修改都会影响到原变量。例如,当a是一个列表,执行b = a后,修改b的元素也会同时修改a的元素,因为它们指向同一个列表。 不过,用户可能混淆了赋值与拷贝的概念。在Python中,赋值不是拷贝操作,既不深也不浅。拷贝需要使用特定的方法,比如列表的copy方法(浅拷贝)、copy模块的copy函数(浅拷贝deepcopy函数(深拷贝)。因此,回答时需要明确区分赋值拷贝的不同,并举例说明不同情况下的行为。 接下来,我需要考虑用户可能的疑问点。例如,用户可能认为赋值后修改新变量不会影响原变量,但实际上会,尤其是对于可变对象。因此,需要举例说明这一点,并指出不可变对象的情况(如元组、字符串)在修改时会创建新对象,而不会影响原变量,但这与拷贝无关,而是因为不可变对象本身的特性。 然后,我需要组织回答的结构,确保逻辑清晰。首先明确回答赋值不是拷贝,而是引用同一个对象。然后解释浅拷贝深拷贝的区别,并说明如何通过不同方法实现这两种拷贝。最后,通过示例代码展示不同操作的结果,帮助用户理解。 同时,需要注意使用中文术语的准确性,比如“引用”、“可变对象”、“不可变对象”等。还要确保示例代码的正确性,比如使用列表的浅拷贝深拷贝后的修改情况,展示它们对原对象的影响差异。 可能还需要提醒用户,在处理嵌套结构或包含其他可变对象的对象时,深拷贝的重要性。例如,一个列表中包含另一个列表,浅拷贝只会复制外层列表的引用,内层列表仍然共享,而深拷贝会递归复制所有层级的对象,确保完全独立。 最后,总结关键点,强调赋值与拷贝的区别,以及在不同情况下选择适当的拷贝方式,避免因共享引用导致意外的副作用。</think>在Python中,**直接赋值既不是深拷贝也不是浅拷贝**,而是创建了原对象的引用(别名)。具体行为取决于操作方式,以下是详细说明: --- ### 一、直接赋值本质 ```python a = [1, 2, [3]] b = a # 直接赋值 ``` - **内存关系**:$b$$a$指向同一个内存对象 - **修改影响**: ```python b.append(4) print(a) # 输出 [1, 2, [3], 4](同步变化) ``` --- ### 二、浅拷贝 vs 深拷贝 | 操作 | 方法 | 特点 | 嵌套结构影响 | |---------------------|-------------------------------|--------------------------------------|-----------------------------| | **浅拷贝** | `copy.copy()` 或 `list.copy()` | 只复制顶层对象,子对象保持引用 | 修改嵌套元素会互相影响 | | **深拷贝** | `copy.deepcopy()` | 递归复制所有层级对象 | 完全独立,无相互影响 | --- ### 三、示例对比 #### 1. 浅拷贝示例 ```python import copy original = [1, [2, 3]] shallow = copy.copy(original) # 修改顶层元素 shallow[0] = 100 print(original) # 输出 [1, [2, 3]](无影响) # 修改嵌套元素 shallow[1].append(4) print(original) # 输出 [1, [2, 3, 4]](同步变化) ``` #### 2. 深拷贝示例 ```python import copy original = [1, [2, 3]] deep = copy.deepcopy(original) # 修改任何层级元素 deep[1].append(4) print(original) # 保持 [1, [2, 3]](完全独立) ``` --- ### 四、可视化对比 ``` 原始对象 浅拷贝对象 深拷贝对象 ┌───┬───┐ ┌───┬───┐ ┌───┬───┐ │ 1 │ ●─┼─────▶│ 1 │ ●─┼─────┐ │ 1 │ ●───┐ └───┴─┬─┘ └───┴─┬─┘ │ └───┴─┬─┘ │ ▼ ▼ │ ▼ │ ┌───┬───┐ ┌───┬───┐ │ ┌───┬───┐ │2 │ 3 │ │2 │ 3 │◀─┘ │2 │ 3 │ └───┴───┘ └───┴───┘ └───┴───┘ ``` --- ### 五、核心结论 1. **赋值操作**:创建引用(所有修改同步) 2. **浅拷贝**:适合单层结构(嵌套部分仍共享) 3. **深拷贝**:适合多层嵌套结构(完全独立) 通过合理选择拷贝方式,可以避免因对象共享引用导致的意外修改问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我辈李想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值