详解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中if __name__ == "__main__"详细解释
Oct 21 Python
Python魔术方法详解
Feb 14 Python
Python 中迭代器与生成器实例详解
Mar 29 Python
详解Python做一个名片管理系统
Mar 14 Python
Django+zTree构建组织架构树的方法
Aug 21 Python
python使用多线程编写tcp客户端程序
Sep 02 Python
OpenCV+Python--RGB转HSI的实现
Nov 27 Python
Python爬虫实现HTTP网络请求多种实现方式
Jun 19 Python
获取python运行输出的数据并解析存为dataFrame实例
Jul 07 Python
django restframework serializer 增加自定义字段操作
Jul 15 Python
python用分数表示矩阵的方法实例
Jan 11 Python
C3 线性化算法与 MRO之Python中的多继承
Oct 05 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教程之PHP中shell脚本的使用方法分享
2012/02/23 PHP
apache mysql php 源码编译使用方法
2012/05/03 PHP
探讨:parse url解析URL,返回其组成部分
2013/06/14 PHP
thinkphp框架实现删除和批量删除
2016/06/29 PHP
PHP用函数嵌入网站访问量计数器
2017/10/27 PHP
Yii框架ACF(accessController)简单权限控制操作示例
2019/04/26 PHP
YII框架页面缓存操作示例
2019/04/29 PHP
HTML IMG标签 onload 内存溢出导致浏览器CPU占用过高
2021/03/09 Javascript
JS判断、校验MAC地址的2个实例
2014/05/05 Javascript
javascript中的throttle和debounce浅析
2014/06/06 Javascript
js实现select选择框效果及美化
2016/08/19 Javascript
jquery动态创建div与input的实例代码
2016/10/12 Javascript
html、css和jquery相结合实现简单的进度条效果实例代码
2016/10/24 Javascript
解析预加载显示图片艺术
2016/12/05 Javascript
jQuery点击导航栏选中更换样式的实现代码
2017/01/23 Javascript
javascript实现右下角广告框效果
2017/02/01 Javascript
详解NodeJs开发微信公众号
2018/05/25 NodeJs
浅谈webpack4.x 入门(一篇足矣)
2018/09/05 Javascript
[01:15]PWL S2开团时刻第二期——他们杀 我就白给
2020/11/25 DOTA
python中的一些类型转换函数小结
2013/02/10 Python
Python 的内置字符串方法小结
2016/03/15 Python
python用win32gui遍历窗口并设置窗口位置的方法
2019/07/26 Python
django将数组传递给前台模板的方法
2019/08/06 Python
tornado+celery的简单使用详解
2019/12/21 Python
python求最大公约数和最小公倍数的简单方法
2020/02/13 Python
Python生成六万个随机,唯一的8位数字和数字组成的随机字符串实例
2020/03/03 Python
Numpy实现卷积神经网络(CNN)的示例
2020/10/09 Python
CSS3 @keyframes简单动画实现
2018/02/24 HTML / CSS
函授本科毕业自我鉴定
2013/10/09 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
中班上学期幼儿评语
2014/04/30 职场文书
学生顶撞老师的检讨书
2014/09/17 职场文书
教师节表彰会主持词
2015/07/06 职场文书
2016大学生暑期三下乡心得体会
2016/01/23 职场文书
彩虹社八名人气艺人全新周边限时推出,性转女装男装一次拥有!
2022/04/01 日漫
LyScript实现绕过反调试保护的示例详解
2022/08/14 Python