8.内存分析-深浅拷贝

程序软件在计算机中运行,需要运算的数据是加载到内存中的,由CPU从内存中读取数据完成数据的运算过程,返回数据结果给内存。

(1) 内存模型

内存条是计算机中的一个物理组件,主要用来临时存储运行程序的数据。
栈内存:可以临时存储数据,存储数据的速度快,但是稳定性差
堆内存:可以长期存储数据,存储数据的速度慢,但是稳定性高
常量区:可以永久存储软件中经常使用的固定数据
资源区:可以存储程序运行的基本资源数据,如运行的二进制代码
在这里插入图片描述

(2)字符串内存

①字符串赋值

# 字符串赋值
>>> name1 = "maomao"
>>> name2 = "maomao"
>>> print(id(name1))
2402697453040
>>> print(id(name2))
2402697453040

②字符串修改

# 字符串修改
name = "TOM"
name = "JERRY"

内存分析:name =“JERRY"执行时,在常量区中查询是否存在"JERRY”,如果存在就直接使用(不需要再申请内存空间),如果不存在就申请内存空间创建数据,将内存地址赋值给变量,通过变量就可以找到内存地址,通过内存地址找到具体的数据.
结论:字符串数据不能修改,将字符串数据称为不可变类型的数据

③字符串操作

# 字符串操作
s1 = "hello"
s2 = "world"
s3 = "helloworld"
s4 = s1 + s2

内存分析:Python认为如果字符串直接是字面量赋值,这样的数据是需要重复使用的,就直接在常量区开辟内存空间存放数据;如果是通过运算得到的字符串数据,这样的数据一半都是动态变化的,不需要在内存中永久存储,所以运算得到的字符串数据,这样的数据一般都是动态变化的,不需要在内存中永久存储,所以运算得到的字符串数据会在堆内存中分配.

(3) 整数内存

整数类型,在进行数据赋值和修改的时候,在内存中并没有修改原有数据,而是直接申请内存增加了新的数据,所以整数类型也是不可变类型

① 一个代码块中的整数

>>> i1 = 1200;i2 = 1200;
>>> i1
1200
>>> i2
1200
>>> print(id(i1),id(i2))
2637913689648 2637913689648

内存分析:解释器本来是解释一行代码,执行一行代码;但是一个python文件通常会一次性加载到内存中(代码会有一个预加载检查的过程),发现i1赋值了1200,在进行i2赋值时,会检查常量区,如果存在1200的数据就直接赋值给i2(不需要重新申请空间,提高数据复用,提高程序处理效率)

② 非同一代码块的整数

>>> i1 = 1200
>>> i2 = 1200
>>> i2
1200
>>> i1
1200
>>> print(id(i1),id(i2))
1674033139248 1674033139312
>>> del i1
>>> del i2
>>> i3 = 1200
>>> print(id(i3))
1674033884752
>>> 

内存分析:解释器(交互模式下没有预加载检查操作)在给i1赋值时,直接解释执行在常量区申请空间存储1200数据;解释器在给i2赋值时直接在常量区申请空间存储1200数据,两部分变量赋值操作都是独立解释运行的,内存中出现了重复的数据(这个跟交互模式的使用场景有关,交互模式经常用来进行少量代码的运行测试,所以每次执行单行代码块时都会独立申请内存,防止多个代码块之间的数据互相影响,造成测试结果出错).

③ 特定整数

python中对常用的整数提供了一种优化模式,解释器将一些常用的整数数据提前加载到了常量区了,如果我们使用这些特定整数(-5<=x<=256),可以不用申请空间,直接给变量赋值.

(4) 列表内存

列表中可以存储任意类型的多个数据,并且列表内部的数据是可以进行修改更换,所以列表是一种可变类型的数据类型

# 声明一个列表,存储不同类型的数据
lst = ["钟无艳", "橘右京",  True, 18]

在这里插入图片描述

② 列表数据的修改

# 声明一个列表,存储不同类型的数据
lst = ["钟无艳", "橘右京",  True, 18]
lst[1] = "马可波罗"  # 修改数据

在这里插入图片描述

深浅拷贝

拷贝 : 就是复制
Python针对数据,有一种创建副本数据的方式,根据复制数据方式的不同区分为深浅拷贝

(1)引用赋值

多个变量指向同一个数据

# 引用赋值:两个变量指向同一个数据
n1 = "TOM"
n2 = n1
# n1变量和n2变量,指向的是同一个数据

# 引用赋值
l1 = ["孙膑", "姜子牙"]
l2 = l1

(2) 浅拷贝

进行数据复制时,只复制内存地址指向的数据

# 浅拷贝
import copy
新的变量 = copy.copy(要复制的数据)

lst1 = [ ["后羿"], "姜子牙", "孙膑" ]
lst2 = copy.copy(lst1)    # lst2就是一个数据副本:浅拷贝
-----------------------------------------------------互相不影响
>>> del lst1[2]
>>>
>>> lst1
[ ["后羿"], "姜子牙"]	
>>> lst2
[['后羿'], '孙膑', '姜子牙']
-----------------------------------------------------互相影响
>>> lst1[0].append("鲁班七号")
>>>
>>> lst1
[['后羿', '鲁班七号'], '姜子牙']
>>> lst2
[['后羿', '鲁班七号'],'姜子牙', '孙膑']

内存分析:浅拷贝模式下的列表
在这里插入图片描述

(3) 深拷贝

进行数据复制时,先复制内存地址指向的数据,如果这个数据又是一个内存地址,继续复制内存地址指向的数据,直到所有的数据全部复制完毕.

import copy

lst1 = [ ["后羿"],  "孙膑", "姜子牙"]
lst2 = copy.deepcopy()

del lst1[2]
lst1 -->   [ ["后羿"],  "孙膑"]
lst2 -->   [ ["后羿"],  "孙膑", "姜子牙"]

lst1[0].append("鲁班七号")
lst1 --> [ ["后羿", "鲁班七号"],  "孙膑"]
lst2 --> [ ["后羿"],  "孙膑", "姜子牙"]

内存分析
在这里插入图片描述
1、引用赋值,没有发生数据变化,仅仅是多个变量指向同一个数据
2、浅拷贝,只拷贝变量内存地址指向的数据,不再继续拷贝数据内部的地址数据
3、深拷贝,完整拷贝目标数据中所有的不可变类型的数据

(3).关于元组

元组: 可以存储存储有顺序的,可以重复的,可以是不同数据类型的数据,但是一旦存储不能修改.元组是一种不可变类型

>>> t = (1,2,3,4)
>>> t[0] = 10
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    t[0] = 10
TypeError: 'tuple' object does not support item assignment

>>> t2 = (1,2,[3,4])
>>> t2[2].append(5)
>>> t2
(1, 2, [3, 4, 5])

内存分析
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值