详解python的内存分配机制


Posted in Python onMay 10, 2021

开始

作为一个实例,让我们创建四个变量并为其赋值:

variable1 = 1
variable2 = "abc"
variable3 = (1,2)
variable4 = ['a',1]

#打印他们的ids
print('Variable1: ', id(variable1))
print('Variable2: ', id(variable2))
print('Variable3: ', id(variable3))
print('Variable4: ', id(variable4))

打印结果如下所示:

变量1:1747938368
变量2:152386423976
变量3:152382712136
变量4:152382633160

每个变量都被分配了一个新的内存地址(以整数形式表示)。第一个假设是,每当我们使用“ =”给变量赋值时,Python都会创建一个新的内存地址来存储变量。这是100%正确的吗?当然不是!

我将创建两个新变量(5和6)并使用现有变量的值给它们赋值。

variable5 = variable1
variable6 = variable4

print('Variable1: ', id(variable1))
print('Variable4: ', id(variable4))
print('Variable5: ', id(variable5))
print('Variable6: ', id(variable6))

Python打印结果:

变量1:1747938368
变量4:819035469000
变量5:1747938368
变量6:819035469000

你注意到,Python并未为这两个变量创建新的内存地址吗?这次,它只是把两个新变量都指向了现有变量相同的存储位置。

现在让我们为变量1设置一个新值。注意:整数是不可变数据类型。

print('Variable1: ', id(variable1))
variable1 = 2
print('Variable1: ', id(variable1))

这将打印:

Variable1: 1747938368
Variable1: 1747938400

这意味着每当我们使用=并将新值给现有变量赋值时,就会在内部创建一个新的内存地址来存储该变量。让我们看看它是否成立!

当值是可变数据类型时会发生什么?variable6是一个列表,让我们在列表结尾append一个值并打印其内存地址:

print('Variable6:',id(variable6))
variable6.append('new')
print('Variable6:',id(variable6))

请注意,变量的内存地址保持不变,因为它是可变数据类型,我们仅更新了其元素。

Variable6:678181106888
Variable6:678181106888

让我们创建一个函数并将一个变量传递给它。如果我们在函数内部设置变量的值,它会发生什么?让我们评估一下。

def update_variable(variable_to_update):
    print(id(variable_to_update))
update_variable(variable6)
print('Variable6: ', id(variable6))

请注意,variable_to_update的ID指向变量6的ID。

这意味着如果我们在函数中更新variable_to_update且variable_to_update是可变数据类型,那么variable6的值将更新。我们看一个具体例子:

variable6 = ['new']
print('Variable6: ', variable6)

def update_variable(variable_to_update):
    variable_to_update.append('inside')
update_variable(variable6)
print('Variable6: ', variable6)

这将打印:

Variable6:['new']
Variable6:['new','inside']

它向我们展示了如何在函数中的更新一个可变的变量,你可以看到函数类和函数外的可变变量都具有相同的ID。

如果我们在函数内给变量赋一个新值(而不是更新),无论它是不可变的还是可变的数据类型,那么一旦退出函数,更改将丢失:

print('Variable6: ', variable6)

def update_variable(variable_to_update):
    print(id(variable_to_update))
    variable_to_update = ['inside']
update_variable(variable6)
print('Variable6: ', variable6)

Variable6:['new']
344115201992
Variable6:['new']

现在是一个有趣的场景:Python并不总是为所有新变量创建一个新的内存地址。

最后,如果我们为两个不同的变量分配一个字符串值,例如“ a”,该怎么办?它会创建两个内存地址吗?

variable_nine ="a"
variable_ten ="a"
print('Variable9:',id(variable_nine))
print('Variable10:',id(variable_ten))

注意,这两个变量具有相同的内存位置:

Variable9:792473698064
Variable10:792473698064

如果我们创建两个不同的变量并为其分配一个长字符串值,该怎么办:

variable_nine = "a" * 21
variable_ten = "a" * 21
print('Variable9: ', id(variable_nine))
print('Variable10: ', id(variable_ten))

这次Python为两个变量创建了两个不同内存位置:

Variable9:541949933872
Variable10:541949933944

为什么? 这是因为Python启动时会创建一个内部值缓存,这样做是为了提供更快的结果。Python会为少量整数(如-5到256之间)和较小的字符串值分配了少量的内存地址。这就是我们示例中的短字符串都具有相同ID的原因,而长字符串的ID则不同。

== vs是

有时我们想检查两个对象是否相等。

  • 如果我们使用==,它将检查两个参数是否包含相同的数据
  • 如果我们使用is,那么Python将检查两个对象是否引用相同的对象,此时两个对象的id必须相同
var1 = "a" * 30 
var2 = "a" * 30 
print('var1:',id(var1))#318966315648 
print('var2:',id(var2))#168966317364 

print('==:', var1 == var2)#返回True 
print('is:',var1 is var2)#返回False

以上就是详解python的内存分配机制的详细内容,更多关于python 内存分配机制的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python分析nignx访问日志脚本分享
Feb 26 Python
python 队列详解及实例代码
Oct 18 Python
将TensorFlow的模型网络导出为单个文件的方法
Apr 23 Python
Python一个简单的通信程序(客户端 服务器)
Mar 06 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
Apr 04 Python
Python学习笔记基本数据结构之序列类型list tuple range用法分析
Jun 08 Python
python 实现返回一个列表中出现次数最多的元素方法
Jun 11 Python
Pandas删除数据的几种情况(小结)
Jun 21 Python
利用Python进行图像的加法,图像混合(附代码)
Jul 14 Python
python输出pdf文档的实例
Feb 13 Python
Pytorch实现WGAN用于动漫头像生成
Mar 04 Python
4种非常实用的python内置数据结构
Apr 28 Python
python-for x in range的用法(注意要点、细节)
May 10 #Python
Django显示可视化图表的实践
python 中[0]*2与0*2的区别说明
May 10 #Python
Python超简单容易上手的画图工具库推荐
python爬虫请求库httpx和parsel解析库的使用测评
May 10 #Python
Python 中数组和数字相乘时的注意事项说明
May 10 #Python
python 实现的截屏工具
You might like
用php写的serv-u的web申请账号的程序
2006/10/09 PHP
基于pear auth实现登录验证
2010/02/26 PHP
PHP中extract()函数的定义和用法
2012/08/17 PHP
php的ddos攻击解决方法
2015/01/08 PHP
PHP自定义函数获取汉字首字母的方法
2016/12/01 PHP
在laravel框架中实现封装公共方法全局调用
2019/10/14 PHP
javascript 年月日联动实现核心代码
2009/12/21 Javascript
jquery zTree异步加载简单实例分享
2013/02/05 Javascript
基于jquery实现省市联动特效
2015/12/17 Javascript
JavaScript中setTimeout和setInterval函数的传参及调用
2016/03/11 Javascript
AngularJS基础 ng-class-odd 指令示例
2016/08/01 Javascript
BootStrap轮播HTML代码(推荐)
2016/12/10 Javascript
利用iscroll4实现轮播图效果实例代码
2017/01/11 Javascript
jQuery实现的下雪动画效果示例【附源码下载】
2018/02/02 jQuery
vue+vuex+json-seiver实现数据展示+分页功能
2019/04/11 Javascript
vue2.0基于vue-cli+element-ui制作树形treeTable
2019/04/30 Javascript
解决vue动态路由异步加载import组件,加载不到module的问题
2020/07/26 Javascript
vue集成一个支持图片缩放拖拽的富文本编辑器
2021/01/29 Vue.js
python中使用pyhook实现键盘监控的例子
2014/07/18 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
2019/05/23 Python
Python调用C语言的实现
2019/07/26 Python
scrapy数据存储在mysql数据库的两种方式(同步和异步)
2020/02/18 Python
Python实现分数序列求和
2020/02/25 Python
python实现全排列代码(回溯、深度优先搜索)
2020/02/26 Python
keras 回调函数Callbacks 断点ModelCheckpoint教程
2020/06/18 Python
python Matplotlib数据可视化(1):简单入门
2020/09/30 Python
基于python实现监听Rabbitmq系统日志代码示例
2020/11/28 Python
美国最大的烧烤架和户外生活用品专业零售商:Barbeques Galore
2021/01/09 全球购物
通信生自我鉴定
2014/01/18 职场文书
自行车广告词大全
2014/03/21 职场文书
市场营销专业应届生自荐信
2014/06/19 职场文书
平面设计专业求职信
2014/08/09 职场文书
2014入党积极分子破除“四风”思想汇报
2014/09/14 职场文书
2014年信贷员工作总结
2014/11/18 职场文书
用CSS3画一个爱心
2021/04/27 HTML / CSS
实体类或对象序列化时,忽略为空属性的操作
2021/06/30 Java/Android