Python变量存储方式以及深浅拷贝

本文详细解析Python中变量的存储机制,包括动态语言特性、内存分配原理及深浅拷贝的区别。深入探讨了不同数据类型(如字符串、数字、列表、字典)在赋值、浅拷贝和深拷贝时的内存行为。

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

Python变量存储方式以及深浅拷贝

(关于学习廖雪峰Python教程的一些个人总结)

变量存储

Python是动态语言。

可以把任意数据类型赋值给变量,无需提前声明变量类型,同一个变量可以反复赋值,而且可以是不同类型的变量。

下面引用廖雪峰Python教程的简单例子,描述变量存储过程:

当我们写

a = 'ABC'

时,Python解释器干了两件事情:

  1. 在内存中创建了一个'ABC'的字符串;
  2. 在内存中创建了一个名为a的变量,并把它指向'ABC'

下面程序

a = 'ABC'
b = a
a = 'XYZ'
print(b)
# >>> ABC

执行过程:

执行a = 'ABC',解释器创建了字符串'ABC'和变量a,并把a指向'ABC'

py-var-code-1

执行b = a,解释器创建了变量b,并把b指向a指向的字符串'ABC'

py-var-code-2

执行a = 'XYZ',解释器创建了字符串’XYZ’,并把a的指向改为'XYZ',但b并没有更改:

py-var-code-3

所以,最后打印变量b的结果是'ABC'了。


深浅拷贝

Python当中对于拷贝,按照拷贝数据类型分为两种类型。一种是数字和字符串的拷贝,另一种就是列表、元组、字典等其他数据结构类型的拷贝。

当然按照深浅也分深拷贝和浅拷贝。

一、数组和字符串拷贝

1、= 赋值

举例:

a1 = 123
a2 = 123
print(id(a1))
print(id(a2))

结果:(在你的电脑试验和这里的地址肯定不同)

140723824476816
140723824476816

原因是Python有一个重用机制,对于同一个数字,Python并不会开辟一块新的内存空间,而是维护同一块内存地址,a1,a2变量指向数字123的地址。等同于a2 = a1,使用字符串赋值也是同理。

结论:对于通过用 = 号赋值,数字和字符串在内存当中用的都是同一块地址。

2、浅拷贝

举例:

import copy  # 使用浅拷贝需要导入copy模块
a1 = 123
a3 = copy.copy(a1)  # 使用copy模块里的copy()函数就是浅拷贝
print(id(a1))
print(id(a3))

结果:(在你的电脑试验和这里的地址肯定不同)

140723824476816
140723824476816

发现地址还是一样。

结论:对于浅拷贝,数字和字符串在内存当中用的也是同一块地址,和上面讲的原理相同。

3、深拷贝

举例:

import copy
a1 = 123
a4 = copy.deepcopy(a1)  # 深拷贝是用copy模块里的deepcopy()函数
print(id(a1))
print(id(a4))

结果:(在你的电脑试验和这里的地址肯定不同)

140723824476816
140723824476816

发现地址还是一样。

结论:对于深拷贝,数字和字符串在内存当中用的也是同一块地址,和上面讲的原理相同。

综上所述,对于数字和字符串的赋值、浅拷贝、深拷贝在内存当中用的都是同一块地址。

在这里插入图片描述

二、字典,列表,元组等数据结构类型拷贝

1、=赋值

举例:

dict1 = {'k1': 'wu', 'k2': 123, 'k3': {1: 'alex', 2: 678}}
dict2 = dict1
print(id(dict1))
print(id(dict2))

结果:(在你的电脑试验和这里的地址肯定不同)

2331901131440
2331901131440

dict2变量只是指向了同一份字典数据的地址,如下图所示:

在这里插入图片描述

理解了上面的图我们看一下下面的代码:

dict1 = dict1['k3']
dict2 = dict1
dict2[3] = 'hiahia'
print(dict1)

我们逐步看怎么执行的:

dict1 = dict1['k3']

在这里插入图片描述

dict2 = dict1

在这里插入图片描述

dict2[3] = 'hiahia'

在这里插入图片描述

print(dict1)

所以结果是:

{1: 'alex', 2: 678, 3: 'hiahia'}
2. 浅拷贝

举例:

import copy
dict1 = {"k1": "wu", "k2": 123, "k3": {1: 'alex', 2: 678}}
dict3 = copy.copy(dict1)  # 浅拷贝
print("第一层字典的内存地址:")
print(id(dict1))
print(id(dict3))
print("第二层嵌套的列表的内存地址:")
print(id(dict1["k3"]))
print(id(dict3["k3"]))

结果:(在你的电脑试验和这里的地址肯定不同)

第一层字典的内存地址:
2331901131872
2331901132088
第二层嵌套的列表的内存地址:
2331901155272
2331901155272

结果发现字典第一层确实被拷贝了,变成了两个,但第二层还是共用相同的数据,如下图:

在这里插入图片描述

结论:所以对于浅拷贝,字典、列表、元组等类型,它们只拷贝第一层地址。

3、深拷贝

举例:

import copy
dict1 = {"k1": "wu", "k2": 123, "k3": {1: 'alex', 2: 678}}
dict4 = copy.deepcopy(dict1)  # 深拷贝
print("第一层字典的内存地址:")
print(id(dict1))
print(id(dict4))
print("第二层嵌套的列表的内存地址:")
print(id(dict1["k3"]))
print(id(dict4["k3"]))
print("第三层嵌套的列表的内存地址:")
print(id(dict1["k3"][1]))
print(id(dict4["k3"][1]))

结果:(在你的电脑试验和这里的地址肯定不同)

第一层字典的内存地址:
2331901131872
2331901132376
第二层嵌套的列表的内存地址:
2331901155272
2331901091976
第三层嵌套的列表的内存地址:
2331901150912
2331901150912

发现一二层被拷贝了,最底层的数字和字符串数据依然共用,如下图:

在这里插入图片描述

结论:对于深拷贝,字典、列表、元组等类型,它里面嵌套多少层,就会拷贝多少层出来,但是最底层的数字和字符串地址不变。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值