Python:Python进阶:内存管理机制

news2024/11/16 21:33:35

Python内存管理机制

  • 1. 堆
  • 2. 栈
  • 3. 引用
  • 4. Python中可变对象和不可变对象
  • 有个问题:你可以好好思考下
  • 总结

Python内存管理程序是用 C/C++写的,这里我们以 CPython解释器为例说明。
在Python 中 所有数据类型 包括:int dict str都是一个对象,叫做 PyObject 。

在这里插入图片描述

下面,我主要从 堆栈 ,引用这三个方面来浅析 CPython 内存管理机制

1. 堆

主要负责存储 CPython运行时的所有对象实体 (也就是 Python对象的所有属性数据),例如:
smt = 'Hello, world ’ 是一个 PyASCIIObject
n = 23 是一个 整数 PyLongObject

  1. 上面两个例子,他们都是 Python对象。
  2. 赋值符号 “=” 右边的是 数据值,CPython 会将其存储到 堆内存中。

2. 栈

在CPython的语义中,又叫数据栈或值栈,它主要负责保存对堆中 Python对象的引用。
smt = ‘Hello, World’ , CPython会将 ‘Hello,World’ 这个字符串实体所处的内存地址压入栈中, 而不是将 ‘Hello,world’ 实体压入栈中。
smt 仅仅 持有对该Python对象实体的引用 。

3. 引用

我们先看这个示例

s1 = 'hello world'
s2 = 'hello world'
print(id(s1))  # 2028548222256
print(id(s2))  # 2028548222256
print(s1==s2) # True
  1. 示例中表明:变量s1和s2 持有Python 对象在堆内存相同的地址。这个可以从打印出的 引用的内存地址和 Python 判断两个对象是否相等(==) 都可以看出来。
  2. 现在我们来,分析下上面引用地址相同原因
    💚💚💚
  3. 变量 s1持有Python对象 ‘Hello world’ 引用,对于CPython虚拟机来说:在 执行 s1 = ‘Hello world’ 时,将内存地址 0x71334 压入内存栈。
  4. 当 CPython碰到同样的 语句 s2 = ‘Hello world’ ,由于指向同一个PythonObject对象,那么 s2 和 s1一样,自然也会持有 ‘Hello world’引用,即 s2 实质上也拥有 ‘Hello world’ 堆中的地址。
    在这里插入图片描述

4. Python中可变对象和不可变对象

我们已 列表对象作为研究主题

L = [11,12,32,45]
print("1.打印列表中的元素所在地址")
for X in L:
    print(id(X))

print("2.打印列表对象L的内存地址:",id(L))
print("3.修改第三个元素: 734")
L[2] = 734

print("4.再次打印列表中元素的内存地址")
for X in L:
    print(id(X))
    
print("5.打印列表对象L的内存地址: ",id(L))

# 打印运行结果
1.打印列表中的元素所在地址
2655576719920
2655576719952
*2655576720592*
2655576721008
2.打印列表对象L的内存地址: 2656002024640
3.修改第三个元素
4.再次打印列表中元素的内存地址
2655576719920
2655576719952
*2655577763760*
2655576721008
5.打印列表对象L的内存地址:  2656002024640

根据上述代码和运行结果可知如下事实:

  • list 类型的 L 本身 是一个 Python对象,其对象实体就是在 堆内存中。
  • list 类型的对象,作为一个容器级别的对象,其列表存储的是元素实体 的引用,而非 元素实体本身。
  • 对 list 对象中的某个元素修改的本质 是 :让被修改元素指向其他元素的引用。修改该元素时,实际上CPython 在堆内存中创建一个新的对象来分配新的内存空间,并且保存该新增的对象(整数734),所以 list对象的第三个元素 L(2) 不再保存对 整数32 引用,更新为对 734 的引用。
  • 但是list类型对象在其元素修改前后,变量L对象 始终引用同一个 list对象。
    在这里插入图片描述
    从上面的例子我们也可以知道
  1. 可变对象:其内部元素可修改是指:变更对其他 Python对象的引用(如:列表中第二个元素 L[2] ),可变对象的元素 可以是:数字,字符串,甚至是其他容器级别的可变对象
  2. 不可变对象:上面示例中list 的元素都是不可变对象,Python中原始数据类型,如:数字类型(int, float) 字符串(str) 字节数字(bytes)

有个问题:你可以好好思考下

我们知道,整数类型是右值,理论上应该返回具体值,但是为什么能返回内存地址了 ?
💚💚💚
回答这个问题之前,我们需要知道:在Python中,一切事物都是对象,不论是整数,字符串,甚至是其他容器级别的数据类型,都是由CPython的C 底层由一个叫 struct PyObject 结构体所封装。

  1. PyObject的结构体在 CPython运行时存储在堆中,对于C底层来说,任意的PyObject结构体 返回的是内存地址,因此它是一个左值
  2. 但是对于 Python语义来说,不存在 静态语言汇总的左值和右值,它只能理解的是 PyObject 这个C实现的对象。

总结

我们理解了CPython的基本内存模型后,但要说的是,这是一个简化的内存模型, CPython虚拟机对于堆内存管理有一套较为复杂的内存池管理方案。通过上面的分析,我们知道了 Python内存管理的两个基本概念

  1. 什么是 CPython的栈引用
  2. 什么是 CPython对象的引用
    我们从堆内存的角度理解为什么 CPython要对 Python对象分类 可变对象和不可变对象,这是因为 Python 变量持有 Python对象的引用(从C的角度就是:Python变量持有PyObject对象的指针)去访问 Python 对象实体本身,比持有 Python 对象实体的副本 更高效,更节省堆和栈内存开销
  3. 当 多个Python变量 引用同一个 Python对象就 会涉及到 引用计数器,引用计数器属于内存垃圾回收的范畴,由引用计数又会 牵扯出 CPython一个致命 的诟病,GIL(全局解释器锁),为什么这么多年CPython不能去掉 GIL ,很大原因就是引用计数器有关。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/503676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

层次分析法及找工作问题实战

学习知识要实时简单回顾,我把学习的层次分析法简单梳理一下,方便入门与复习。 AHP 层次分析法(Analytic Hierarchy Process,简称 AHP)是对一些较为复杂、较为模糊的问题作出决策的简易方法,它特别适用于那…

C++类和对象上

专栏:C/C 个人主页:HaiFan. 专栏简介:本章为大家带来C类和对象相关内容。 类和对象 前言面向过程和面向对象类的引入类的定义对于类中成员的命名建议 类的访问限定符及封装访问限定符封装 类的作用域类的实例化如何计算类对象的大小this指针t…

Web自动化测试——XAPTH高级定位

XAPTH高级定位 一、xpath 基本概念二、xpath 使用场景三、xpath 相对定位的优点四、xpath 定位的调试方法五、xpath 基础语法(包含关系)六、xpath 顺序关系(索引)七、xpath 高级用法1、[last()]: 选取最后一个2、[属性名属性值 an…

ESP32设备驱动-PCF8575IO扩展器驱动

PCF8575IO扩展器驱动 文章目录 PCF8575IO扩展器驱动1、PCF8575介绍2、硬件准备3、软件准备4、驱动实现1、PCF8575介绍 PCF8575用于两线双向总线 (I2C) 的 16 位 I/O 扩展器专为 2.5-V 至 5.5-V VCC 操作而设计。 PCF8575 器件通过 I2C 接口 [串行时钟 (SCL)、串行数据 (SDA)]…

flask教程8:模板

文章目录 一、模板与自定义过滤器1 模板2 过滤器转义过滤器讲解 3自定义过滤器 二、表单1表单2表单扩展 三、创建表单模型类与模板使用3.1 表单模型类 四 、使用表单接受并检验参数五、模板宏的使用六 、宏定义在外部的使用七 :模板继承与包含继承包含include 八 、…

PVE 安装 windows10

pve 安装教程大家可以参考视频:pve 安装 pve 安装 Windows10 视频教程:pve 安装Windows10 在安装好 pve 后我们就可以进行虚拟机的安装了。当然我们可以自行决定是否有必要进行 win10 的安装。 准备工作 1. 下载 win10 镜像文件:https://…

数据结构与算法基础(王卓)(35):交换排序之快排【第二阶段:标准答案、初步发现问题】

目录 第二阶段:一分为二 整个快排算法的程序运行大框架: 做出的改动(和原来程序的区别): Project 1: PPT标准答案: Project 1小问题: Project 1还存在着一个巨大的问题: 具体问…

嵌入式软考备考_8 软件测试

软件测试 测试:在规定的条件下操作程序,以发现错误,对软件质量进行评估。 对象:程序,数据,文档。 目的:发现错误,看是否满足用户需求,发现错误产生的原因(…

汇编四、51单片机汇编指令2

1、机器码 (1)MOV A,#0x60对应机器码为7460 (2)7460对应二进制 0111 0100 0110 0000 0x74对应指令,0x60对应立即数。 (3)immediate data翻译为立即数。 (4)可人为查表把汇编转为机器码,也可通过编译器把汇编转为机器码。 2、汇编常见缩写 (1)Rn: n可…

leetcode-040-组合总和2

题目及测试 package pid040; /* 40. 组合总和 II 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用 一次 。注意:解集不能包含重复的组合…

Vue中使用EasyPlayer播放H265视频流

需求说明 需要在Vue2的项目中使用EasyPlayer进行H265视频流的播放。使用官方的最新版本加载H265会有问题。一直处于加载中… 实现步骤 引入easyplayer,这里最开始引入了最新版会有问题,因此引入的是3.3.12版本,可参照官方文档进行配置。 EasyPlayer示…

HBase整合Phoenix

HBase整合Phoenix 创建软件目录 mkdir -p /opt/soft cd /opt/soft下载软件 wget https://dlcdn.apache.org/phoenix/phoenix-5.1.3/phoenix-hbase-2.5-5.1.3-bin.tar.gz解压 hbase tar -zxvf phoenix-hbase-2.5-5.1.3-bin.tar.gz修改 hbase 目录名称 mv phoenix-hbase-2.5…

(初)进程概念

目录 认识冯诺依曼系统 操作系统(Operator System) 设计OS的目的: 定位: 如何理解管理: 总结: 系统调用和库函数概念: 进程 基本概念 : 描述进程PCB task_struct - PCB的一种 task_struct内容分…

编译安装最新的Linux系统内核

现在还有不少机器是CentOS8 Stream系统,虽然上了贼船,不影响用就是了。8的编译和7大同小异,只是踩了更多的坑在这里记录一下,或许会帮到看到的朋友。 安装编译环境 CentOS8安装必要的包 yum groupinstall "Development Too…

【P13】JMeter 常数吞吐量定时器(Constant Throughput Timer)

文章目录 1、基于计算吞吐量:只有此线程2、基于计算吞吐量:所有活动线程3、基于计算吞吐量:当前线程组中的所有活动线程4、基于计算吞吐量:所有活动线程(共享)5、基于计算吞吐量:当前线程组中的…

【2023/05/08】雅卡尔织布机

Hello!大家好,我是霜淮子,2023倒计时第3天。 Share The world puts off its mask of vastness to its lover. It becomes small as one song,as one kiss of the eternal. 译文: 世界对着它的爱人,把它浩瀚的面具揭…

已做过算法题总结2

20. 有效的括号 (括号匹配是使用栈解决的经典问题,这道题主要是记住三种不成立的情况) 给定一个只包括 (,),{,},[,] 的字符串,判断字符串是否有效。 有效字符串需满足: 左括号必须用…

解密链表元素移除:三种巧妙思路,轻松驱逐难缠结点

本篇博客会讲解力扣“203. 移除链表元素”的解题思路,这是题目链接。 老规矩,先来审题: 以下是一些示例: 以下是提示: 本题的思路还挺多的,不过都是链表的常规操作。 思路1 万能的尾插法。遍历链表&am…

[Golang] 爬虫实战-用多层嵌套结构体去接收多层嵌套数据

😚一个不甘平凡的普通人,致力于为Golang社区和算法学习做出贡献,期待您的关注和认可,陪您一起学习打卡!!!😘😘😘 🤗专栏:算法学习 &am…

量子计算(10)编程实践2:隐形传态算法

目录 一、算法目的 二、算法原理 三、pyqpanda实现代码 四、测试结果 一、算法目的 量子隐形传态,又称量子遥传、量子隐形传输、量子隐形传送、量子远距传输或量子远传,是一种利用分散量子缠结与一些物理讯息的转换来传送量子态至任意距离的位置的技…