Loading...
墨滴

瀋凣

2021/07/21  阅读:25  主题:极简黑

python笔记17

Python day17

1. 引用

变量并不是盒子,而是更像是一个标签。在Python中,当赋值运算发生的时候,Python并不是把数据放到变量里面,而是让数据和变量进行挂钩,而这个过程就叫做引用

引用
引用

补充: Python内存分析[1]

Python的内存机制和Java差不多,分为栈内存区堆内存区常量区数据区

换一句别人的话来说:内存空间在逻辑上分为三部分:代码区、静态数据区和动态数据区,动态数据区又分为栈区和堆区

内存划分
内存划分

栈内存区
栈内存(Stack):栈内存比较小,但是速度快。一般存储运行方法的形参、局部变量、返回值。由系统自动分配和回收

堆内存
堆内存(Heap):对内存一般比较大,但是速度慢。一般放对象

静态存储区
静态存储区(Stastic):这个区域也可以叫做常量池。存储全局变量、静态变量、常量,常量包括final修饰的常量和String常量。系统自动分配和回收

数据区
数据区(Data):这个区域专门加载代码字节数据,方法数据、函数等.高级调度(作业调度)、中级调度(内存调度)、低级调度(进程调度)控制代码区执行代码的切换.


变量在内存中的存储

可变数据和不可变数据

  • 可变数据:列表(list)、字典(dict)
  • 不可变数据:整型(int)、浮点型(float)、字符串型(String)、元组(tuple)

为什么要区别可变和不可变?

这里的可变和不可变指的是内存中的那块内容是否可变,当数据是可变的时候,对数据进行操作时并不需要重新申请新的内存空间,只需要在此数据空间后连续申请即可。而当数据是不可变时,对数据进行一些操作的时候是需要重新在内存中申请一段新的空间,来存放新的数据。


举个栗子:

a = "Hello"
b = 3
c = ["Hello"3]
print(id(a), id(b))   # 140415037732720 93831947674432
print(id(c[0]), id(c[1]))  # 140415037732720 93831947674432
上述代码内存分析
上述代码内存分析

因为 Hello 和 3 都是常量,所以打印出来的内存地址是相同的


回到正题~

举个栗子:
>>> x = [1,2,3]
>>> y = x
>>> y
[123]
>>> x[1] = 0
>>> x
[103]
>>> y
[103]

所以想要得到两个独立的列表,就要通过拷贝来完成。

“烤(扇)贝”
“烤(扇)贝”

2. 浅拷贝和深拷贝

2.1 浅拷贝

利用我们之前学过的copy()方法就可以实现浅拷贝:

>>> x = [1,2,3]
>>> y = x.copy()
>>> y
[123]
>>> x[1] = 0
>>> x
[103]
>>> y
[123]
浅拷贝
浅拷贝

还可以利用切片的方式实现浅拷贝:

>>> x = [123]
>>> y = x[:]
>>> y
[123]
>>> x[1] = 0
>>> x
[103]
>>> y
[123]

浅拷贝对于一维列表的处理是一点问题都没有的,但是当要处理对象变为二维列表时,令人难堪的情况又出来了:

>>> x = [[123], [456], [789]]
>>> y = x.copy()
>>> y
[[123], [456], [789]]
>>> x[1][1] = 0
>>> x
[[123], [406], [789]]
>>> y
[[123], [406], [789]]

之所以会发生这种情况,是因为浅拷贝只能拷贝到外层对象,如果包含嵌套对象的话,拷贝的只是其引用。

浅拷贝
浅拷贝

面对这种情况,我们就要使用深拷贝

2.2 深拷贝

想要实现深拷贝,就要借助copy模块。

  • 引入copy模块
>>> import copy 

copy模块包含两个函数:

copy(x)
deepcopy(x)
#x为要拷贝的对象

通过模块名.的方式调用这两个函数。

copy.copy(x)
copy.deepcopy(x)

2.2.1 copy(x)

功能和列表的copy()方法一样,实现的是浅拷贝:

>>> x = [[123], [456], [789]]
>>> y = copy.copy(x)
>>> y = [[123], [456], [789]]
>>> x[1][1] = 0
>>> x
[[123], [406], [789]]
>>> y
[[123], [406], [789]]

2.2.2 deepcopy(x)

实现深拷贝:

>>> x = [[123], [456], [789]]
>>> y = copy.deepcopy(x)
>>> y
[[123], [456], [789]]
>>> x[1][1] = 0
>>> x
[[123], [406], [789]]
>>> y
[[123], [456], [789]]

不同于浅拷贝只拷贝外层对象,深拷贝会将内部的对象一并拷贝。

深拷贝
深拷贝

即使是多层嵌套,深拷贝也都会从里到外全部拷贝。

点点关注不迷路
点点关注不迷路

参考资料

[1]

Python内存分析: https://www.cnblogs.com/Fortunater/p/12972765.html

- END -

瀋凣

2021/07/21  阅读:25  主题:极简黑

作者介绍

瀋凣