python申请内存函数_python进阶用法2 【从帮助函数看python内存申请机制】
前言
介绍了四个帮助函数,dir(),help(),type(),id(),通过id()函数进一步分析了python在申请内存方面的效率问题,提到的基本类型有string,list,queue和deque
四个帮助函数
dir()函数
dir()函数是查看函数或模块内的操作方法都有什么,输出的是方法列表。
dir('str')
也可以查看自己定义的函数
help()函数
help()函数是查看函数或模块用途的详细说明,例:
help('str')
type()函数
这个很简单了,返回其类型,略
id()函数
对一个对象的引用调用id()函数,可以得到该对象的标识符(dentity).该标识符是一个整数,它保证在该对象的生命周期内是唯一的和恒定的.具有不重叠生命周期的两个对象具有相同的id()值.
PS: 在CPython实现细节:标识符(dentity)为对象在内存中的地址. 在Python中一切皆对象,变量中存放的是对象的引用.字符串常量和整型常量都是对象.
举个例子:
>>> a = 1
>>> b=2
>>> c =1
>>> id(a)
1521120064
>>> id(b)
1521120096
>>> id(c)
1521120064
不知道,在看这个dentity的时候,有没有发现a与c的地址是相同的!!!
从id()函数看python内存地址申请机制
看个例子:(以下内容来源@Unname_Bao 关于python3中整数数组转bytes的效率问题)
如果还是没有理解的话,接下来看我本地进行的一个非常简单的一个演示脚本测试:
import time
t1 = time.time()
astr = 'a'
for x in range(1,2000000):
astr = astr + str(x)
astr
t2 = time.time()
print(t2-t1)
#10.028913259506226
#[Finished in 10.2s]
import time
t1 = time.time()
astr = list('1'*2000000)
for x in range(1,2000000):
astr[x]=str(x)
bstr = str(astr)
t2 = time.time()
print(t2-t1)
#0.8323781490325928
#[Finished in 1.1s]
为什么差距如此之大呢?这就回到了我们最初提到的a,b,当值改变,会重新去申请内存空间(id改变)。在这第一个例子中,我们不停地改变astr的值,astr即不停地申请内存空间,此过程消耗了大量的时间!!!第二个例子中,我们一次申请了够所有变量使用的内存空间地址,免去了每次申请,所以大大加快了运行速度!!!
感谢@一个闲散之人的闲散更进一步的分析,
影响其效率问题的核心根本在于list到底是基于链表的数据结构还是基于线性表的数据结构。线性表的话为了腾出足够连续空间需要改变表头的内存位置,也就造成了id的改变,对于链表而言,则只需要申请一个结点大小的内存量,没必要对表头的内存位置动手脚。
关于list的数据结构,从知乎上get到的结果是线性表形式的数据结构,于是乎我又做了以下3个测试:
1、不提前申请空间的queue
import time
import queue
t1 = time.time()
astr = queue.Queue()
for x in range(1,2000000):
astr.put(str(x))
bstr = str(astr)
t2 = time.time()
print(t2-t1)
# 4.525705337524414
# [Finished in 4.8s]
2、不提前申请空间的deque
import collections
import time
t1 = time.time()
astr = collections.deque()
for x in range(1,2000000):
astr.append(str(x))
bstr = str(astr)
t2 = time.time()
print(t2-t1)
# 0.938164234161377
# [Finished in 1.3s]
3、不提前申请空间的list
import time
t1 = time.time()
astr = []
for x in range(1,2000000):
astr.append(str(x))
bstr = str(astr)
t2 = time.time()
print(t2-t1)
# 0.9456796646118164
# [Finished in 1.2s]
另做个测试:
import collections
import queue
print("Deque ID:")
astr1 = collections.deque()
for x in range(1,5):
astr1.append(str(x))
print(id(astr1))
print("Queue ID:")
astr2 = queue.Queue()
for x in range(1,5):
astr2.put(str(x))
print(id(astr2))
print("list ID:")
astr3 = []
for x in range(1,5):
astr3.append(str(x))
print(id(astr3))
# Deque ID:
# 1206229307464
# 1206229307464
# 1206229307464
# 1206229307464
# Queue ID:
# 1206225595416
# 1206225595416
# 1206225595416
# 1206225595416
# list ID:
# 1206229266760
# 1206229266760
# 1206229266760
# 1206229266760
# [Finished in 0.2s]
queue、deque其实可以很明显看出,其均是依靠c的链表进行开发的(不需要提前申请空间),其地址亦不变化。更改一点之前的错误理解,python的list实现不是链表,而是动态数组
当我们使用deque时,可以很明显看到,我们的时间消耗已经差距很小了,与未提前申请空间的list接近一致,但经多次运行,还是可以发现,最快的依旧是已经申请了空间的list,我么进一步去了解queue和deque可以发现其无法提前申请空间(可以理解为其职能分别从一端和两段进行增加值,减值),及无法像list一样可以通过list[下标]直接取值,所以综上所述,list无疑是最快的~
补充,list的扩张空间机制
>>> test = []
>>> test.__sizeof__()
40
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
72
>>> test.append('a')
>>> test.__sizeof__()
104
>>>
参考链接:Python中list的内存分配
python申请内存函数_python进阶用法2 【从帮助函数看python内存申请机制】相关推荐
- python神秘的魔法函数_python进阶之魔法函数
__repr__ Python中这个__repr__函数,对应repr(object)这个函数,返回一个可以用来表示对象的可打印字符串. 如果我们直接打印一个类,向下面这样 class A(): de ...
- python order函数_Python进阶内容(一)--- 高阶函数 High order function
0. 问题 # 本文将围绕这段代码进行Python中高阶函数相关内容的讲解 # 文中所有代码的兼容性要求为:Python 3.6,IPython 6.1.0 def addspam(fn): def ...
- python tracer函数_Python流程控制常用工具和函数定义
在我们的工作中,我们使用ddagent ver.5作为收集工具,收集和报告托管服务器的性能指标,并对ddagent进行一定程度的定制.经过多次功能迭代,发现一批在线运行时间长的托管服务器占用了太多内存 ...
- python语言接收信息的内置函数_python接收信息的内置函数是
有的python内置函数怎么就一个pass这个模块是用C实现的,没有Python源码. 所以python代码中只有一个pass,因为代码中都是C实现的. 两种情况: 一种情况是继承的时候会用到的,父类 ...
- python查看模块功能_Python进阶之inspect模块使用详解
前几篇内容我们详细探讨了如何从Python中获取帮助信息: 前情回顾 1.查看模块.类提供了哪些接口: 需要帮助吗?dir函数的孪生兄弟,Python中魔法方法__dir__详解 2.查看对象内部属性 ...
- python重复执行函数_Python threading 单线程 timer重复调用函数
项目中需要使用定时器,每次都使用构造器函数调用: timer = threading.Timer(timerFlag, upload_position) timer.start() 打印线程后发现,每 ...
- python 协程 多线程_python进阶之多线程(简单介绍协程)
多线程 线程:实现多任务的另一种方式 一个进程中,也经常需要同时做多件事,就需要同时运行多个'子任务',这些子任务,就是线程 线程又被称为轻量级进程(lightweight process),是更小的 ...
- python io密集 多线程_Python进阶:聊聊IO密集型任务、计算密集型任务,以及多线程、多进程...
IO密集型任务 VS 计算密集型任务所谓IO密集型任务,是指磁盘IO.网络IO占主要的任务,计算量很小.比如请求网页.读写文件等.当然我们在Python中可以利用sleep达到IO密集型任务的目的. ...
- python 定义list长度_python中list列表的高级函数 python如何统计列表的长度
在python的函数中,如何将列表list的一部分作为函比如定义个函数,想实现的功能就是将列表a的后半部分(['c','d'])传入后面paraTestList(a[2:])中,括号里面的a[2:]命 ...
最新文章
- js轮播图代码_javascript基础(一)——轮播图
- 指纹图谱相似度评价软件_远志与炆远志指纹图谱比较
- 如何由jdk的安装版本改成非安装版本
- 听说用 Lombok 可以早点下班?
- virtualbox+vagrant安装虚拟机
- HBase MapReduce
- leetcode - 621. 任务调度器
- 大学生职业生涯规划计划与路径_我校举办2020年大学生职业生涯规划大赛
- Docker笔记4 端口映射和容器互联
- js正则替换html字符串,js正则找出字符串的内容,并替换内容
- Gson解析原理概述
- idea合并svn不同分支_如何在Intellij IDEA中使用svn合并分支到主干?
- 高数七重积分的总结_高数下册总结
- mooc作业怎么上传附件_产创云操作指南(五):作业系统的使用(学生端)
- 怎样设置和检测浏览器语言
- 回答阿里云实名认证常见问题
- 金蝶各版本软件迁移到金蝶K3WISE工具补丁合集
- 稚晖君_瀚文机械键盘2
- airsim-使用Image api保存机载摄像机的图片
- 别了,IE浏览器?微软正式宣布
热门文章
- 通过Idea创建spring项目,没有spring Initializr选项的解决方法
- 揭秘TensorFlow:Google开源到底开的是什么?
- 3.4.1 计算机网络之流量控制(停止-等待协议、滑动窗口、后退N帧协议GBN、选择重传协议SR)、滑动窗口、可靠传输机制
- 利用oc门或od门实现线与_景县专业门球场专用人造草坪甄选博翔远
- float 与 double、隐式类型转换、switch、重写与重载、Java 与 C++ 的区别、JRE or JDK
- 华硕笔记本节能证书_新标准兼顾性能与续航 笔记本换代哪些型号值得买?
- Palo Doris不会用?(基础指南)
- c语言中穷竭算法,hihocoder#1054 : 滑动解锁(深度优先搜索)
- django restful 请求_Django编写RESTful API(二):请求和响应
- Java通过Pattern类使用正则表达式