探索 Python 的动态类型系统:变量引用、不可变性及高效内存管理与垃圾回收机制的深入分析

devtools/2024/10/18 23:27:03/

文章目录

    • 1. 动态类型及其内存管理解析
      • 1.1 变量与对象的引用关系
      • 1.2 对象的不可变性和内存地址的变化
    • 2. 垃圾回收与内存优化策略

Python作为一种流行的高级编程语言,以其代码的易读性和简洁性著称。尤其是它的动态类型系统和自动内存管理,使得开发者可以更加专注于实现功能而非处理底层细节。下面就来讲讲,今天面试被问到了。


1. 动态类型及其内存管理解析

Python 作为一种动态类型的编程语言,允许开发者在声明变量时不需要指定数据类型。此外,Python 中的一切皆为对象,变量则是对这些对象的引用。

1.1 变量与对象的引用关系

同一个对象可以被多个变量引用

python"># 创建变量 x 并赋值为 10
x = 10
print("变量 x 的类型:", type(x)) # 变量 x 的类型: <class 'int'># 创建变量 y,将其引用设置为变量 x 的引用
y = x
print("x 引用的对象地址:", hex(id(x))) # 0x7ff0ab01a3d0
print("y 引用的对象地址:", hex(id(y)))# 0x7ff0ab01a3d0

xy 都引用了同一个整数对象 10

补充:hex() 用于将一个整数转换成对应的十六进制字符串

1.2 对象的不可变性和内存地址的变化

修改 x 的值,并观察 xy 的引用是否发生变化:

python"># 修改变量 x 的值
x += 1
print("修改后 x 的地址:", hex(id(x))) # 修改后 x 的地址: 0x7ff0ab01a3f0

当对 x 进行加 1 操作时,由于整数是不可变类型,x 指向了一个新的整数对象 11,而原有的整数对象 10 保持不变。

2. 垃圾回收与内存优化策略

Python的动态类型允许程序在运行时创建、修改和销毁对象,这种灵活性虽然提供了极大的便利,但也带来了对内存管理机制的依赖。

2.1 动态内存分配的基础

在 Python 中,变量在创建时不需要声明数据类型,因此,Python 需要在运行时动态地管理内存。这主要通过堆内存来实现,其中对象的创建、修改和销毁都在堆内存中进行。

python">def bar(a):a = a - 1return adef foo(a):a = a * ab = bar(a)return bdef main():x = 2y = foo(x)if __name__ == "__main__":main()

main 函数被调用时,局部变量 xy 被创建并存储在调用栈上,而通过 foobar 函数创建的对象则存储在堆上。当 foobar 函数执行完毕后,它们可能会在堆上留下未被回收的对象,这就是动态内存管理中需要解决的问题。

运行时:

在这里插入图片描述

运行结束:

在这里插入图片描述

2.2 Python 的垃圾回收

Python 通过一个内置的垃圾收集器来管理内存,它主要使用引用计数和标记-清除算法来追踪和清除不再使用的对象。

引用计数: Python 对每个对象维护一个引用计数,每当对象的引用数变为零时,该对象就会被垃圾收集器回收。

python">import sysclass Color:def __init__(self, r, g, b):self.red = rself.green = gself.blue = bclr = Color(255, 0, 0)
print("clr 对象的引用计数:", sys.getrefcount(clr) - 1)  
# 减1是因为getrefcount在调用时也会增加一次引用计数

循环引用问题: 引用计数方法不能处理对象间的循环引用,例如两个对象互相引用。


推荐: python 错误记录
参考:Python Memory Management


http://www.ppmy.cn/devtools/16179.html

相关文章

代码随想录算法训练营第23天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树 、总结

代码随想录算法训练营第23天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树 、总结 自己看到题目的第一想法看完代码随想录之后的想法自己实现过程中遇到哪些困难总结 链接: 669. 修剪二叉搜索树 链接: 108.将有序数组转换为二叉搜索树…

线程池学习

一、线程池基础 1、什么是线程池 用一句话来概述就是&#xff1a;线程池是指在初始化一个多线程应用程序过程中创建一个线程集合&#xff0c;然后再需要执行新的任务时重用这些线程而不是新建线程。 2、为什么使用线程池 使用线程池最大的原因就是可以根据系统的需求和硬件环境…

如何使用rdtsc和C/C++来测量运行时间(如何使用内联汇编和获取CPU的TSC时钟频率)

本文主要是一个实验和思维扩展&#xff0c;是一个初步的尝试&#xff0c;旨在研究一些时间测量实现和在 C/C 中内联汇编和汇编函数的使用方法。除非你有特殊用途&#xff0c;不然不要使用汇编指令来实现这个功能。在“扩展阅读”部分会列出了一些不需要内联汇编实现的方法。 写…

个人博客系统的设计与实现

https://download.csdn.net/download/liuhaikang/89222885http://点击下载源码和论文 本 科 毕 业 设 计&#xff08;论文&#xff09; 题 目&#xff1a;个人博客系统的设计与实现 专题题目&#xff1a; 本 科 毕 业 设 计&#xff08;论文&#xff09;任 务 书 题 …

代码随想录算法训练营day9 | 28. 实现 strStr()、459.重复的子字符串

28. 实现 strStr() 暴力解法&#xff1a;双重循环&#xff0c;外层是haystack字符串&#xff0c;内层是needle字符串 KMP算法&#xff1a;当haystack字符串和needle字符串已经匹配部分之后&#xff0c;如果下一个不匹配后&#xff0c;暴力法将会从头开始匹配&#xff0c;已经…

树莓集团携手国际数字影像产业园代表企业与天府新区信息职业学院达成战略合作

2024年4月16日&#xff0c;树莓科技&#xff08;成都&#xff09;集团有限公司作为国际数字影像产业园的运营方及链主企业&#xff0c;携手园区代表企业成都奇琦汇嘉供应链科技有限公司、成都树莓友品数字技术有限公司&#xff0c;一同前往天府新区信息职业学院进行考察并开展产…

vue 手写手动轮播 且图片宽度不一样

vue 手写手动轮播 且图片宽度不一样 轮播图样式 <div class"case-imgs" v-if"length ! 0"><div :class"[length 1 ? big : small, imgs-wrapper]"><img class"case-img" v-for"(m, n) in activeParam.imgs"…

Java操作 elasticsearch 8.1,如何实现索引的重建?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…