详解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获取操作系统信息实例
Sep 02 Python
Python爬虫实例_利用百度地图API批量获取城市所有的POI点
Jan 10 Python
Python输出各行命令详解
Feb 01 Python
python实现手机通讯录搜索功能
Feb 22 Python
利用Pyhton中的requests包进行网页访问测试的方法
Dec 26 Python
Python3.4解释器用法简单示例
Mar 22 Python
详解Python利用random生成一个列表内的随机数
Aug 21 Python
Python reshape的用法及多个二维数组合并为三维数组的实例
Feb 07 Python
使用python的pyplot绘制函数实例
Feb 13 Python
基于Keras的格式化输出Loss实现方式
Jun 17 Python
基于python爬取梨视频实现过程解析
Nov 09 Python
利用python进行文件操作
Dec 04 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对包含html标签的字符串进行截取的函数分享
2014/06/19 PHP
destoon实现调用图文新闻的方法
2014/08/21 PHP
详解PHP的Yii框架中扩展的安装与使用
2016/04/01 PHP
PHP中trait使用方法详细介绍
2017/05/21 PHP
CI框架网页缓存简单用法分析
2018/12/26 PHP
Prototype 学习 工具函数学习($方法)
2009/07/12 Javascript
javascript 获取url参数和script标签中获取url参数函数代码
2010/01/22 Javascript
JS对象转换为Jquery对象示例
2014/01/26 Javascript
JavaScript删除数组元素的方法
2015/03/20 Javascript
使用JQuery选择HTML遍历函数的方法
2016/09/17 Javascript
JavaScript与JQUERY获取元素的宽、高和位置
2017/02/26 Javascript
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
2017/09/18 Javascript
Angular模版驱动表单的使用总结
2018/05/05 Javascript
promise和co搭配生成器函数方式解决js代码异步流程的比较
2018/05/25 Javascript
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
2018/05/26 jQuery
vue 自动化路由实现代码
2019/09/03 Javascript
layui插件表单验证提交触发提交的例子
2019/09/09 Javascript
vue实现select下拉显示隐藏功能
2019/09/30 Javascript
解决Idea、WebStorm下使用Vue cli脚手架项目无法使用Webpack别名的问题
2019/10/11 Javascript
浅谈element中InfiniteScroll按需引入的一点注意事项
2020/06/05 Javascript
[19:24]DOTA2客户端使用指南 一分钟快速设置轻松超神
2013/09/24 DOTA
python基础教程之lambda表达式使用方法
2014/02/12 Python
wxpython 最小化到托盘与欢迎图片的实现方法
2014/06/09 Python
使用Python脚本将绝对url替换为相对url的教程
2015/04/24 Python
Django中实现点击图片链接强制直接下载的方法
2015/05/14 Python
Python中单、双下划线的区别总结
2017/12/01 Python
Python学习笔记之视频人脸检测识别实例教程
2019/03/06 Python
利用python如何在前程无忧高效投递简历
2019/05/07 Python
Python学习笔记之While循环用法分析
2019/08/14 Python
python中hasattr()、getattr()、setattr()函数的使用
2019/08/16 Python
零基础小白多久能学会python
2020/06/22 Python
python Scrapy框架原理解析
2021/01/04 Python
XML文档面试题
2015/08/05 面试题
《孔子游春》教学反思
2014/02/25 职场文书
Golang ort 中的sortInts 方法
2022/04/24 Golang
Golang并发工具Singleflight
2022/05/06 Golang