前言

介绍了四个帮助函数,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内存申请机制】相关推荐

  1. python神秘的魔法函数_python进阶之魔法函数

    __repr__ Python中这个__repr__函数,对应repr(object)这个函数,返回一个可以用来表示对象的可打印字符串. 如果我们直接打印一个类,向下面这样 class A(): de ...

  2. python order函数_Python进阶内容(一)--- 高阶函数 High order function

    0. 问题 # 本文将围绕这段代码进行Python中高阶函数相关内容的讲解 # 文中所有代码的兼容性要求为:Python 3.6,IPython 6.1.0 def addspam(fn): def ...

  3. python tracer函数_Python流程控制常用工具和函数定义

    在我们的工作中,我们使用ddagent ver.5作为收集工具,收集和报告托管服务器的性能指标,并对ddagent进行一定程度的定制.经过多次功能迭代,发现一批在线运行时间长的托管服务器占用了太多内存 ...

  4. python语言接收信息的内置函数_python接收信息的内置函数是

    有的python内置函数怎么就一个pass这个模块是用C实现的,没有Python源码. 所以python代码中只有一个pass,因为代码中都是C实现的. 两种情况: 一种情况是继承的时候会用到的,父类 ...

  5. python查看模块功能_Python进阶之inspect模块使用详解

    前几篇内容我们详细探讨了如何从Python中获取帮助信息: 前情回顾 1.查看模块.类提供了哪些接口: 需要帮助吗?dir函数的孪生兄弟,Python中魔法方法__dir__详解 2.查看对象内部属性 ...

  6. python重复执行函数_Python threading 单线程 timer重复调用函数

    项目中需要使用定时器,每次都使用构造器函数调用: timer = threading.Timer(timerFlag, upload_position) timer.start() 打印线程后发现,每 ...

  7. python 协程 多线程_python进阶之多线程(简单介绍协程)

    多线程 线程:实现多任务的另一种方式 一个进程中,也经常需要同时做多件事,就需要同时运行多个'子任务',这些子任务,就是线程 线程又被称为轻量级进程(lightweight process),是更小的 ...

  8. python io密集 多线程_Python进阶:聊聊IO密集型任务、计算密集型任务,以及多线程、多进程...

    IO密集型任务 VS 计算密集型任务所谓IO密集型任务,是指磁盘IO.网络IO占主要的任务,计算量很小.比如请求网页.读写文件等.当然我们在Python中可以利用sleep达到IO密集型任务的目的. ...

  9. python 定义list长度_python中list列表的高级函数 python如何统计列表的长度

    在python的函数中,如何将列表list的一部分作为函比如定义个函数,想实现的功能就是将列表a的后半部分(['c','d'])传入后面paraTestList(a[2:])中,括号里面的a[2:]命 ...

最新文章

  1. js轮播图代码_javascript基础(一)——轮播图
  2. 指纹图谱相似度评价软件_远志与炆远志指纹图谱比较
  3. 如何由jdk的安装版本改成非安装版本
  4. 听说用 Lombok 可以早点下班?
  5. virtualbox+vagrant安装虚拟机
  6. HBase MapReduce
  7. leetcode - 621. 任务调度器
  8. 大学生职业生涯规划计划与路径_我校举办2020年大学生职业生涯规划大赛
  9. Docker笔记4 端口映射和容器互联
  10. js正则替换html字符串,js正则找出字符串的内容,并替换内容
  11. Gson解析原理概述
  12. idea合并svn不同分支_如何在Intellij IDEA中使用svn合并分支到主干?
  13. 高数七重积分的总结_高数下册总结
  14. mooc作业怎么上传附件_产创云操作指南(五):作业系统的使用(学生端)
  15. 怎样设置和检测浏览器语言
  16. 回答阿里云实名认证常见问题
  17. 金蝶各版本软件迁移到金蝶K3WISE工具补丁合集
  18. 稚晖君_瀚文机械键盘2
  19. airsim-使用Image api保存机载摄像机的图片
  20. 别了,IE浏览器?微软正式宣布

热门文章

  1. 通过Idea创建spring项目,没有spring Initializr选项的解决方法
  2. 揭秘TensorFlow:Google开源到底开的是什么?
  3. 3.4.1 计算机网络之流量控制(停止-等待协议、滑动窗口、后退N帧协议GBN、选择重传协议SR)、滑动窗口、可靠传输机制
  4. 利用oc门或od门实现线与_景县专业门球场专用人造草坪甄选博翔远
  5. float 与 double、隐式类型转换、switch、重写与重载、Java 与 C++ 的区别、JRE or JDK
  6. 华硕笔记本节能证书_新标准兼顾性能与续航 笔记本换代哪些型号值得买?
  7. Palo Doris不会用?(基础指南)
  8. c语言中穷竭算法,hihocoder#1054 : 滑动解锁(深度优先搜索)
  9. django restful 请求_Django编写RESTful API(二):请求和响应
  10. Java通过Pattern类使用正则表达式