python做内存辅助_pubg辅助_Python一切皆是工具,但这和内存治理有什么关系?
今天是Python的第15篇文章,我们来聊聊Python中内存管理机制,以及循环引用的问题。
Python的内存管理机制
对于工程师而言,内存管理机制异常主要,是绕不外去的一环。若是你是Java工程师,面试的时刻一定会问JVM。C 工程师也一定会问内存泄露,同样我们想要深入学习Python,内存管理机制也是绕不外去的一环。
不外幸亏Python的内存管理机制相对来说比较简朴,我们也不用稀奇深入其中的细节,简朴做个领会即可。
Python内存管理机制的焦点就是引用计数,在Python当中一切都是工具,工具通过引用来使用。
我们看到的是变量名,然则变量名指向了内存当中的一块工具。这种关系在Python当中称为引用,我们通过引用来操作工具。以是凭据这点,引用计数很好明白,也就是说我们会对每一个工具举行统计所有指向它的指针的数目。若是一个工具引用计数为0,那么说明它没有任何引用指向它,也就是说它已经没有在使用了,这个时刻,Python就会将这块内存收回。
简朴来说引用计数原理就是这些,但我们稍微深入一点,来简朴看看哪些场景会引起工具引用的转变。
引用计数的转变显然只有两种,一种是增添,一种是削减,这两种场景都只有4种情形。我们先来看下增添的情形:
首先是初始化,最简朴的就是我们用
赋值操作给一个变量赋值。举个例子:
n = 123
这就是最简朴的初始化操作,虽然123在我们来看是一个常数,然则在Python底层同样被认为是一个常数工具。n是它的一个引用。
第二种情形是引用的通报,最简朴的就是我们将一个变量的值赋值给了另外一个变量。
m = n
好比我们将n赋值给m,它的本质是我们建立了一个新的引用,指向了同样一块内存。若是我们用id操作去查看m和n的id,会发现它们的id是一样的。也就是说它们并不是存储了两份相同的值,而是指向了统一份值。并不是有两个叫做王小二的人,而是王小二有两个差别的账号。
第三种情形是作为元素被存储进了容器当中,好比被存储进了list当中。
a = [1, 2, 123]
虽然我们用到了一个容器,然则容器并不会拷贝一份这些工具,照样只是存储这些工具的引用。
最后一种情形就是作为参数传给函数,在Python当中,所有的传参都是引用通报。这也是为什么,我们经常看到有人会这样写代码的缘故原由:
def test(a):
a.append(3)
a = []
test(a)
print(a)
我们凭据上面枚举的这四种引用计数增添的情形,不难推导出引用削减的情形, 实在基本上是对称的操作。
和初始化对应的操作是
销毁,好比我们建立的工具被del操作给销毁了,那么同样引用计数会-1
del n
和赋值给其他变量名的操作相反的操作是
笼罩,好比之前我们的n=123,也就是n这个变量指向123,现在我们将n赋值成其他值,那么123这个工具的引用计数同样会削减。
n = 124
既然元素存储在容器当中会带来引用计数,那么同样元素
从容器当中移除也会削减引用计数。这个也很好明白,最简朴的就是list挪用remove方式移除一个元素:
a.remove(123)
最后一个对应的就是作用域,也就是当变量
离开了作用域,那么它对应的内存块的引用计数同样会削减。好比我们函数挪用竣事,那么作为参数的这些变量对应的引用计数都市减1。
若是一个工具的引用计数减到0,也就是没有引用再指向它的时刻,那么当Python举行gc的时刻,这块内存就会被释放,也就是这个工具会被消灭,腾出空间来。
注重一下,引用计数减到0与内存接纳之间并不是立刻发生的,而是有一段距离的。凭据Python的机制,内存接纳只会在特定条件下执行。在占用内存比较小另有许多富足的情形下,往往是不会执行内存接纳的。由于Python在执行gc(garbage collection)的时刻也会stop the world,也就是暂停其他所有的义务,以是这是影响性能的一件事情,只会在有需要的时刻执行。
我们费这么大劲来先容Python中的内存机制,除了向人人科普一下这一块内容之外,更主要的一点是为了引出我们开发的时刻经常遇见的一种情形——循环引用。
循环引用
若是熟悉了Python的引用,来明白循环引用是异常容易的。说白了也很简朴,就是你的一个变量引用我,我的一个变量引用你。,吃鸡辅助,
我们来写一段简朴的代码,来看看循环引用:
class Test:
def __init__(self):
pass
if __name__ == '__main__':
a = Test()
b = Test()
a.t = b
b.t = a
若是你打个断点来看的话,会看到a和b之间的循环引用:
这里是无限睁开的,由于这是一个无限循环。无限循环并不会导致程序溃逃, 也不会带来太大的问题,它的问题只有一个,就是凭据前面先容的引用计数法,a和b的引用永远不能能为0。
也就是说凭据引用计数的原则,这两个变量永远不会被接纳,这显然是不合理的。虽然Python当中专门建立了机制来解决引用循环的问题,然则我们并不知道它什么时刻会被触发。
这个问题在Python当中异常普遍,尤其在我们实现一些数据结构的时刻。举个最简朴的例子就是树中的节点,就是引用循环的。由于父节点会存储所有的孩子,往往孩子节点也会存储父节点的信息。那么这就构成了引用循环。
class Node:
def __init__(self, val, father):
self.val = val
self.father = father
self.childs = []
弱引用
为领会决这个问题,Python中提供了一个叫做弱引用的观点。弱引用本质也是一种引用,然则它不会增添工具的引用计数。也就是说它不能保证它引用的工具一定不会被销毁,只要没有销毁,弱引用就可以返回预期的效果。
弱引用不用我们自己开发,这是Python当中集成的一个现成的模块weakref。
这个模块当中的方式许多,用法也许多,然则我们基本上用不到,一般来说最常用的就是ref方式。通过weakref库中的ref方式,可以返回工具的一个弱引用。我们照样来看个例子:
import weakref
class Test:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
if __name__ == '__main__':
a = Test('a')
b = Test('b')
a.t = weakref.ref(b)
b.t = weakref.ref(a)
print(a.t())
实在照样之前的代码,只是做了一点简朴的改动。一个是我们给Test加上了name这个属性,以及str方式。另一个是我们把直接赋值改成了使用weakref。
这一次我们再打断点进来看的话,就看不到无限循环的情形了:
ref返回的是一个获取引用工具的方式,而不是工具自己。以是我们想要获取这个工具的话,需要再把它当成函数挪用一下。
固然这样很贫苦,我们另有更好的设施,就是使用property注解。通过property注解,我们可以把weakref封装掉,这样在使用的时刻就没有感知了。
import weakref
class Test:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
@property
def node(self):
return None if self._node is None else self._node()
@node.setter
def node(self, node):
self._node = weakref.ref(node)
总结
引用和循环引用都是基于Python自己的机制,若是对这块机制不领会,很容易采坑。由于可能会泛起逻辑是对的,然则有一些意想不到的bug的情形。这种时刻,往往很难通过review代码或者是测试发现,这也是我们学习的瓶颈所在。很容易发现代码已经写得很熟练了,然则一些进阶的代码照样看不懂或者是写不出来,本质上就是由于缺少了对于底层的领会和认知。
循环引用的问题在我们开发代码的时刻还蛮常见的,尤其是涉及到树和图的数据结构的时刻。由于循环引用的关系,很有可能泛起被删除的树仍然占用着空间,内存不足的情形发生。这个时刻使用weakref就很有需要了。
今天的文章就到这里,原创不易,扫码关注我,获取更多精彩文章。
python做内存辅助_pubg辅助_Python一切皆是工具,但这和内存治理有什么关系?相关推荐
- python做大数据的框架_Python+大数据计算平台,PyODPS架构手把手教你搭建
原文链接:http://click.aliyun.com/m/13965/ 在2016年10月的云栖社区在线培训上,来自阿里云大数据事业部的秦续业分享了<双剑合壁--Python和大数据计算平台 ...
- python做接口自动化测试仪器经销商_Python接口自动化测试的实现
接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对性的进行选择,甚至当 ...
- python做一个登录注册界面_python做一个登录注册界面的方法
python做一个登录注册界面的方法 发布时间:2020-08-21 10:37:05 来源:亿速云 阅读:111 作者:小新 这篇文章主要介绍python做一个登录注册界面的方法,文中介绍的非常详细 ...
- python界面开发工 跨平台具_python GUI开发常用工具
Python最大的特点就在于她的快速开发功能.作为一种胶水型语言,python几乎可以渗透在我们编程过程中的各个领域.这里我简单介绍一下用python进行gui开发的一些选择.1.TkinterTki ...
- python做游戏用什么软件_Python 与游戏测试 (小工具篇)
最近在TesterHome游戏测试群里,有时候会看到有童鞋问,游戏测试人员学了Python,可以干点什么. 很多童鞋初学Python,学习了语法和基础类库后,开始迷茫如何实际使用到工作中去,其实Pyt ...
- python做excel数据分析统计服_Python也能做到Excel那样,条件统计轻松解决工作需求...
此系列文章收录在公众号中:数据大宇宙 > 数据处理 >E-pd 转发本文并私信我"python",即可获得Python资料以及更多系列文章(持续更新的) 经常听别人说 ...
- python做一个登录注册界面_Python 实现简单的登录注册界面
Python 实现简单的登录注册界面 注意:编写代码之前需要导入很重要的包 import tkinter as tk import pickle from tkinter import message ...
- python 做表格分析难么_Python处理分析128张Excel表格竟然不到3秒?
不少粉丝留言,想要了解怎么用Python提升处理数据的效率,或者说怎么用Python自动处理多张Excel表格,于是乎便有了本文. 这篇文章算是Python数据分析实战的第二个独立案例. 注:案例12 ...
- python做疫情数据分析的框架_Python制作新冠疫情世界地图
目录 pyecharts模块 简介 Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可.而 Python 是一门富有表达力的语言,很适合用于数据处 ...
最新文章
- swift 方法的局部和外部参数名
- Altium Designer Exception ESocketError in module X2.EXE at 001B15CF (10107) on API 'Socket'
- 动态创建模板列并绑定数据(GridView,Repeater,DataGrid)
- 中英文对照 —— 经济、金融学、财务
- 一文理清HashMap的实现及细节
- LeetCode 363. 矩形区域不超过 K 的最大数值和(DP+set二分查找)
- ARC和MRC 兼容的单例模式
- 正确理解Python函数是第一类对象
- mysql typedefinition_深入浅出Mysql——基础篇
- 2021-06-09反射的类型方法
- proxmox VE 4.4 增加USB 重定向功能
- 泛泰A870L/K/S第三版官方4.4.2原来的系统卡刷机包 (愿自己主动ROOT)
- 关于公布2013年度局青年学术和技术带头人考评与增选结果的通知
- 双人贪吃蛇java 代码_贪吃蛇课设--个人博客
- 易捷行云新一代私有云平滑无感升级|轻运维之升级
- 反编译之脱去乐固加固的壳
- 证券业数据大集中及其风险控制分析
- 回味那些评论有时候也能受教--摘自双鱼座ROM之硬件评论
- 电子词典 C语言实现
- w8系统桌面没有计算机图标,不见了win8系统桌面图标怎么办