Python一切皆是对象,但这和内存管理有什么关系?

Python的内存管理机制.pdf ⼩整数对象池 intern机制 垃圾回收(引⽤计数、标记清除、分代回收) 立即下载

前言

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理。

PS:如有需要Python学习资料的小伙伴可以点击下方链接自行获取

Python免费学习资料、代码以及交流解答点击即可加入


Python的内存管理机制

对于工程师而言,内存管理机制非常重要,是绕不过去的一环。如果你是Java工程师,面试的时候一定会问JVM。C++工程师也一定会问内存泄漏,同样我们想要深入学习Python,内存管理机制也是绕不过去的一环。

不过好在Python的内存管理机制相对来说比较简单,我们也不用特别深入其中的细节,简单做个了解即可。

Python内存管理机制的核心就是引用计数,在Python当中一切都是对象,对象通过引用来使用。

 

 

我们看到的是变量名,但是变量名指向了内存当中的一块对象。这种关系在Python当中称为引用,我们通过引用来操作对象。所以根据这点,引用计数很好理解,也就是说我们会对每一个对象进行统计所有指向它的指针的数量。如果一个对象引用计数为0,那么说明它没有任何引用指向它,也就是说它已经没有在使用了,这个时候,Python就会将这块内存收回。

简单来说引用计数原理就是这些,但我们稍微深入一点,来简单看看哪些场景会引起对象引用的变化。

引用计数的变化显然只有两种,一种是增加,一种是减少,这两种场景都只有4种情况。我们先来看下增加的情况:

首先是初始化,最简单的就是我们用赋值操作给一个变量赋值。举个例子:

 

 

这就是最简单的初始化操作,虽然123在我们来看是一个常数,但是在Python底层同样被认为是一个常数对象。n是它的一个引用。

第二种情况是引用的传递,最简单的就是我们将一个变量的值赋值给了另外一个变量。

 

 

比如我们将n赋值给m,它的本质是我们创建了一个新的引用,指向了同样一块内存。如果我们用id操作去查看m和n的id,会发现它们的id是一样的。也就是说它们并不是存储了两份相同的值,而是指向了同一份值。并不是有两个叫做王小二的人,而是王小二有两个不同的账号。

第三种情况是作为元素被存储进了容器当中,比如被存储进了list当中。

 

 

虽然我们用到了一个容器,但是容器并不会拷贝一份这些对象,还是只是存储这些对象的引用。

最后一种情况就是作为参数传给函数,在Python当中,所有的传参都是引用传递。这也是为什么,我们经常看到有人会这样写代码的原因:

 

 

我们根据上面列举的这四种引用计数增加的情况,不难推导出引用减少的情况, 其实基本上是对称的操作。

和初始化对应的操作是销毁,比如我们创建的对象被del操作给销毁了,那么同样引用计数会-1

 

 

和赋值给其他变量名的操作相反的操作是覆盖,比如之前我们的n=123,也就是n这个变量指向123,现在我们将n赋值成其他值,那么123这个对象的引用计数同样会减少。

 


既然元素存储在容器当中会带来引用计数,那么同样元素从容器当中移除也会减少引用计数。这个也很好理解,最简单的就是list调用remove方法移除一个元素:

 

最后一个对应的就是作用域,也就是当变量离开了作用域,那么它对应的内存块的引用计数同样会减少。比如我们函数调用结束,那么作为参数的这些变量对应的引用计数都会减1。

如果一个对象的引用计数减到0,也就是没有引用再指向它的时候,那么当Python进行gc的时候,这块内存就会被释放,也就是这个对象会被清除,腾出空间来。

注意一下,引用计数减到0与内存回收之间并不是立即发生的,而是有一段间隔的。根据Python的机制,内存回收只会在特定条件下执行。在占用内存比较小还有很多富裕的情况下,往往是不会执行内存回收的。因为Python在执行gc(garbage collection)的时候也会stop the world,也就是暂停其他所有的任务,所以这是影响性能的一件事情,只会在有必要的时候执行。

我们费这么大劲来介绍Python中的内存机制,除了向大家科普一下这一块内容之外,更重要的一点是为了引出我们开发的时候经常遇见的一种情况——循环引用。

循环引用

如果熟悉了Python的引用,来理解循环引用是非常容易的。说白了也很简单,就是你的一个变量引用我,我的一个变量引用你。

我们来写一段简单的代码,来看看循环引用:

 

 

如果你打个断点来看的话,会看到a和b之间的循环引用:

 


这里是无限展开的,因为这是一个无限循环。无限循环并不会导致程序崩溃, 也不会带来太大的问题,它的问题只有一个,就是根据前面介绍的引用计数法,a和b的引用永远不可能为0。

也就是说根据引用计数的原则,这两个变量永远不会被回收,这显然是不合理的。虽然Python当中专门建立了机制来解决引用循环的问题,但是我们并不知道它什么时候会被触发。

这个问题在Python当中非常普遍,尤其在我们实现一些数据结构的时候。举个最简单的例子就是树中的节点,就是引用循环的。因为父节点会存储所有的孩子,往往孩子节点也会存储父节点的信息。那么这就构成了引用循环。

 

弱引用

为了解决这个问题,Python中提供了一个叫做弱引用的概念。弱引用本质也是一种引用,但是它不会增加对象的引用计数。也就是说它不能保证它引用的对象一定不会被销毁,只要没有销毁,弱引用就可以返回预期的结果。

弱引用不用我们自己开发,这是Python当中集成的一个现成的模块weakref。

这个模块当中的方法很多,用法也很多,但是我们基本上用不到,一般来说最常用的就是ref方法。通过weakref库中的ref方法,可以返回对象的一个弱引用。我们还是来看个例子:

 

 

其实还是之前的代码,只是做了一点简单的改动。一个是我们给Test加上了name这个属性,以及str方法。另一个是我们把直接赋值改成了使用weakref。

这一次我们再打断点进来看的话,就看不到无限循环的情况了:

 

 

ref返回的是一个获取引用对象的方法,而不是对象本身。所以我们想要获取这个对象的话,需要再把它当成函数调用一下。

当然这样很麻烦,我们还有更好的办法,就是使用property注解。通过property注解,我们可以把weakref封装掉,这样在使用的时候就没有感知了。

 

总结

引用和循环引用都是基于Python本身的机制,如果对这块机制不了解,很容易采坑。因为可能会出现逻辑是对的,但是有一些意想不到的bug的情况。这种时候,往往很难通过review代码或者是测试发现,这也是我们学习的瓶颈所在。很容易发现代码已经写得很熟练了,但是一些进阶的代码还是看不懂或者是写不出来,本质上就是因为缺少了对于底层的了解和认知。

循环引用的问题在我们开发代码的时候还蛮常见的,尤其是涉及到树和图的数据结构的时候。由于循环引用的关系,很有可能出现被删除的树仍然占用着空间,内存不足的情况发生。这个时候使用weakref就很有必要了。

python内存管理机制 内存管理,对于python这样的动态语言来说,是至关重要的一部分。它很大程度上决定了python的执行效率,对象的创建销毁,都涉及到内存的管理 立即下载

相关推荐

数据仓库的复用性:设计和构建一个高复用性的数仓

数据仓库的复用性是指在数据仓库的设计和使用过程中,能够实现数据、模型、流程、工具等多个层面的重复利用,减少重复开发,提高开发效率,降低维护成本,并增强灵活性和可扩展性。

z1941563559的博客 1307

python内存池机制什么时候消失_python的内存管理机制

Python引入了一个机制:引用计数。引用计数python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。总结一下对象会在一下情况下引用计数加1:1.对象被创建:x=42.另外的别人被创建:y=x3.被作为参数传递给函数:foo(x)4.作为容器对象的一个元素...

weixin_42523718的博客 475

Qt+PCL实战:如何用QVTKOpenGLNativeWidget高效渲染3D点云(附完整代码)

本文深入解析了Qt与PCL结合使用QVTKOpenGLNativeWidget进行高效3D点云渲染的实战技术。通过对比传统QVTKWidget,详细介绍了QVTKOpenGLNativeWidget在渲染效率、内存占用和兼容性方面的显著优势,并提供了完整的代码示例和性能优化策略,助力开发者在工业检测、自动驾驶等领域实现更高效的点云可视化。

keras9composer的博客 687

python的内存管理机制

先从较浅的层面来说,Python的内存管理机制可以从三个方面来讲(1)垃圾回收(2)引用计数(3)内存池机制一、垃圾回收:python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值。对Python语言来讲,对象的类型和内存都是在运行时确定的。这也是为什么我们称Python语言为动态类型的原因(这里我们把动态类型可以简单的归结为对变量内存地址的分配是在运行时自动判断...

姜姜! 244

网络可视化工具netron详细安装流程

netron安装目录1.netron 简介2.不同操作系统下的安装使用方式2.1 在线版本:只要有浏览器就可以2.2 不同操作系统安装使用3.netron支持的网络框架4.netron测试演示 1.netron 简介 在实际的项目中,经过会遇到各种网络模型,需要我们快速去了解网络结构。如果单纯的去看模型文件,脑海中很难直观的浮现网络的架构。 这时,就可以使用netron可视化工具,可以清晰的看到每一层的输入输出,网络总体的架构,而且支持各种不同网络框架,简单好用。 2.不同操作系统下的安装使用方式 2.1

江南研习社 12万+

最新Win10离线安装.NET Framework 3.5的方法(附离线包2022/3/22)

win10 .net framework 3.5离线安装

别告诉我有Bug 27万+

单片机可以用 Python 开发吗?

关注+星标公众号,不错过精彩内容素材来源 | 网络你肯定会好奇:Python现在这么火,为什么很少看到用 Python 开发单片机?那么,单片机究竟可不可以用 Python 开发?单片机本身不能直接运行Python 程序,需要借助 MicroPython 的支持。MicroPython 是 Python 3 语言的精简实现 ,专为微控制器(MCU)和受限环境设计,它包括Python标准库的一小...

strongerHuang 2666

ADS2019学习笔记:三、SPICE model导入

以BZX84-C33 SPICE model为例,学习如何在ADS2019中导入SPICE model。

qq_42945911的博客 6493

python和单片机的用处哪个大_学好单片机的用处大吗?具体有哪些用处

首先单片机主要应用于嵌入式领域,其他领域很少应用而是使用。单片机的应用非常广泛,最开始是“单板机”,它外部附加了PIO,CTC和SIO等外围器件。后来它们都被集成在一个芯片上,故称为“单片机”。实际上,目前的单片机集成度非常高,例如ARM,DSP等,这些实际上也可以认为是“单片机”。只学习单片机和编程语言(主要是汇编和C语言,上位机使用的编程语言暂不说)也是远远不够的,因为一个产品是有硬件和软件组...

weixin_32767301的博客 1117

最新Docker GPU支持全解析:为什么nvidia-smi能用但PyTorch找不到CUDA?

本文深入解析了Docker容器中nvidia-smi命令可用但PyTorch无法调用CUDA的根本原因。关键在于默认配置仅暴露了GPU的utility管理能力,而CUDA计算所需的compute能力未被激活。通过正确设置NVIDIA_DRIVER_CAPABILITIES环境变量为compute,utility,并配合--gpus参数,即可解决此问题,确保AI训练等任务顺利进行。

convnet3designer的博客 239

【WRFDA教程第四期】雷达数据同化(Radar Data Assimilation)

雷达数据同化(Radar Data Assimilation)

WW、forever的博客 1759

类和对象的关系是什么_Python一切皆是对象,但这和内存管理有什么关系?

点击上方蓝字,和我一起学技术。今天是Python的第15篇文章,我们来聊聊Python中内存管理机制,以及循环引用的问题。Python的内存管理机制对于工程师而言,内存管理机制非常重要,是绕不过去的一环。如果你是Java工程师,面试的时候一定会问JVM。C++工程师也一定会问内存泄漏,同样我们想要深入学习Python,内存管理机制也是绕不过去的一环。不过好在Python的内存管理机制相对...

weixin_39664136的博客 97

一张图讲透银行个人外汇业务逻辑和实操

个人外汇业务主要分为结售汇和外币兑换两类,前者满足日常跨境需求,后者因投机属性多数银行已暂停。业务核心是利用汇率波动实现货币兑换,满足支付或投资需求。交易涉及客户分类、主流币种、多种渠道和汇率计算规则,需区分直接/间接标价法判断汇率走势。银行通过"货币兑换"科目核算损益,采用期末折算确认盈亏。监管要求包括5万美元年度额度、合法渠道、真实性原则及大额申报等。随着跨境金融数字化发展,掌握基础逻辑和合规要求是安全参与外汇业务的关键。

银行信息系统应用架构详解 288

python和单片机有什么关系_Python一切皆是对象,但这和内存管理有什么关系?

今天是Python的第15篇文章,我们来聊聊Python中内存管理机制,以及循环引用的问题。Python的内存管理机制对于工程师而言,内存管理机制非常重要,是绕不过去的一环。如果你是Java工程师,面试的时候一定会问JVM。C++工程师也一定会问内存泄漏,同样我们想要深入学习Python,内存管理机制也是绕不过去的一环。不过好在Python的内存管理机制相对来说比较简单,我们也不用特别深入其中的细...

weixin_39729262的博客 188

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

python内存管理_Python一切皆是对象,但这和内存管理有什么关系?

今天是Python的第15篇文章,我们来聊聊Python中内存管理机制,以及循环引用的问题。Python的内存管理机制对于工程师而言,内存管理机制非常重要,是绕不过去的一环。如果你是Java工程师,面试的时候一定会问JVM。C++工程师也一定会问内存泄漏,同样我们想要深入学习Python,内存管理机制也是绕不过去的一环。不过好在Python的内存管理机制相对来说比较简单,我们也不用特别深入其中的细...

weixin_39745345的博客 80

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

python循环计数_Python一切皆是对象,但这和内存管理有什么关系?

今天是Python的第15篇文章,我们来聊聊Python中内存管理机制,以及循环引用的问题。Python的内存管理机制对于工程师而言,内存管理机制非常重要,是绕不过去的一环。如果你是Java工程师,面试的时候一定会问JVM。C++工程师也一定会问内存泄漏,同样我们想要深入学习Python,内存管理机制也是绕不过去的一环。不过好在Python的内存管理机制相对来说比较简单,我们也不用特别深入其中的细...

weixin_42120275的博客 86

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

python 会增加内存吗_Python一切皆是对象,但这和内存管理有什么关系?

今天是Python的第15篇文章,我们来聊聊Python中内存管理机制,以及循环引用的问题。Python的内存管理机制对于工程师而言,内存管理机制非常重要,是绕不过去的一环。如果你是Java工程师,面试的时候一定会问JVM。C++工程师也一定会问内存泄漏,同样我们想要深入学习Python,内存管理机制也是绕不过去的一环。不过好在Python的内存管理机制相对来说比较简单,我们也不用特别深入其中的细...

weixin_39851887的博客 169

Python 基础知识(2)动态类型、对象

目录2. Python 基础知识22.1 Python对象2.2 动态类型2.3 内存管理2.4 IO 编程2.5 结构与布局 2. Python 基础知识2 2.1 Python对象 牢记 python 对象三要素:id,type,value id:唯一标识一个对象(记录对象的内存地址) type:标识对象的类型 value:对象的具体的值 附: a is b 判断 a 和b 两个对象是否...

Robin_Pi的博客 437

python object类_Python中一切皆对象,这个对象究竟是什么?

点击上方蓝字CGRnDStudio关注我们“ CG TD编程技术相关领域自媒体”作者:古明地盆https://www.cnblogs.com/traditional/p/13391098.html关于 Python,你肯定听过这么一句话:"Python中一切皆对象"。没错,在 Python 的世界里,一切都是对象。整型是一个对象、字符串是一个对象、字典是一个对象,甚至 int、str...

weixin_36457551的博客 1988

Python一切皆对象

一切皆对象 # 一切皆对象 def fun_test(name="haha"): print(name) #函数赋给变量是并实列化 my_name=fun_test print(isinstance(my_name,object)) my_name("Xiaohao") 从结果可以看出,函数也是对象 其他类型一样,不在赘述.... type,object,class之间的关系 type——>int——>1 (type——>class——>obj): a=1 b="abc"

爱吃辣椒的锅包肉 139

python查看类型_Python 中的对象模型

你再主动一点点我们就有故事了Python中一切皆对象关于 Python,你肯定听过这么一句话:"Python中一切皆对象"。没错,在 Python 的世界里,一切都是对象。整型是一个对象、字符串是一个对象、字典是一个对象,甚至 int、str、list 等等,再加上我们使用 class 自定义的类,它们也是对象。像 int、str、list 等基本类型,以及我们自定义的类,由于它...

weixin_39574943的博客 266

python查看类型_解密 Python 中的对象模型

(给Python开发者加星标,提升Python技能)作者:古明地盆https://www.cnblogs.com/traditional/p/13391098.htmlPython中一切皆对象关于 Python,你肯定听过这么一句话:"Python中一切皆对象"。没错,在 Python 的世界里,一切都是对象。整型是一个对象、字符串是一个对象、字典是一个对象,甚至 int、str、lis...

weixin_35167817的博客 166
上一篇: 零基础学Python:异常检测及处理
下一篇: 使用python爬取股票基金的最新数据消息,并用Excel绘制树状图一目了然
酸菜鱼编程
博客等级 码龄6年 155粉丝 63原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值