03 | 列表和元组,到底用哪一个?
03 | 列表和元组,到底用哪一个?
讲述:冯永吉
时长07:23大小5.91M
列表和元组基础
列表和元组存储方式的差异
列表和元组的性能
列表和元组的使用场景
总结
思考题
赞 94
提建议
精选留言(232)
- 和你一起搬砖的胡大爷2019-05-15老师能不能讲一下list和tuple的内部实现,里边是linked list 还是array,还是把array linked一下这种。 最后那个问题,类比java,new 是在heap,直接声明就可能在常量区了。老师能讲下Python的vm么,比如内存分配,gc算法之类的。
作者回复: 1. list和tuple的内部实现都是array的形式,list因为可变,所以是一个over-allocate的array,tuple因为不可变,所以长度大小固定。具体可以参照源码list: https://github.com/python/cpython/blob/master/Objects/listobject.c. tuple: https://github.com/python/cpython/blob/master/Objects/tupleobject.c 2. 最后的思考题: 区别主要在于list()是一个function call,Python的function call会创建stack,并且进行一系列参数检查的操作,比较expensive,反观[]是一个内置的C函数,可以直接被调用,因此效率高。 内存分配,GC等等知识会在第二章进阶里面专门讲到。
共 8 条评论219 - Python高效编程2019-05-15元素不需要改变时: 两三个元素,使用 tuple,元素多一点使用namedtuple。 元素需要改变时: 需要高效随机读取,使用list。需要关键字高效查找,采用 dict。去重,使用 set。大型数据节省空间,使用标准库 array。大型数据高效操作,使用 numpy.array。共 3 条评论179
- 看,有只猪2019-05-15[]比list()更快,因为调用list函数有一定的开销,而[]却没有。 这个有点像C语言中的内联函数与函数的差异共 1 条评论144
- 布霆2019-05-15老师请问一下,为什么l = [1, 2, 3]消耗的空间为64字节,而l.append(1), l.append(2), l.append(3)消耗的空间为72字节,这不是相同的列表吗?
作者回复: 列表的over-allocate是在你加入了新元素之后解释器判断得出当前存储空间不够,给你分配额外的空间,因此 l=[], l.append(1), l.append(2), l.append(3)实际分配了4个元素的空间。但是l=[1, 2, 3]直接初始化列表,并没有增加元素的操作,因此只会分配3个元素的空间
共 2 条评论80 - adapt2019-05-15如果一个列表在元组中的话,其实这个元组是”可变”的,只是这个可变只是能改变该列表里的内容。 这一点作者没有讲到哦 。共 6 条评论63
- converse✪2019-05-17针对可以随意嵌套进行总结: - 列表嵌套列表:本质是列表,内部列表和外部列表的内容可以进行修改元素,插入,删除元素。也就是二维数组。 - 列表嵌套元组:本质是列表,所以可以对列表中除元组外的其他元素可以修改插入、删除。但元组中的内容不可以改变。 - 元组嵌套列表:本质是元组,元组中的任何元素不能进行改变,但是对于元素本身是列表的情况,可以对列表中的值进行修改。这是因为:列表对象是不变的,只是的列表中的内容进行变化。列表本来就是动态的。 - 元组嵌套元组:本质元组,元组中的元素还是元组。所以这种情况下,不能进行任何改变。也就是不可变的二维数组。展开54
- 对方正在输入中…2019-05-15python -m timeit 'empty_list = list()' 10000000 loops, best of 3: 0.0829 usec per loop python -m timeit 'empty_list = []' 10000000 loops, best of 3: 0.0218 usec per loop python -m timeit 'empty_list = ()' 100000000 loops, best of 3: 0.0126 usec per loop 测试结果,虽然直接创建元组初始化速度最快,但是由于要用list函数转一道反而不如直接创建列表的速度快。展开共 3 条评论33
- converse✪2019-05-17空list在申请空间时候,是40字节。当加入新元素后会额外多分配空间变成72字节。当加入4个元素后还是72字节。那么问题来了,初始化申请的40字节是什么?感觉一直没有用到?不是用于存储元素的么?共 5 条评论25
- Geek_59f23e2019-05-151、用list()方法构造一个空列表使用的是class list([iterable])的类型构造器,参数可以是一个iterable,如果没有给出参数,构造器将创建一个空列表[ ],相比较而言多了一步class调用和参数判断,所以用 [ ] 直接构造一个空列表的方法速度更快,刚查的官方解释,不知道我理解的对不对。。。 2、敲代码的时候我一般元祖用来传参用的比较多,能用元祖的地方尽量不用列表,这样代码性能好些。展开
作者回复: 1. 区别主要在于list()是一个function call,Python的function call会创建stack,并且进行一系列参数检查的操作,比较expensive,反观[]是一个内置的C函数,可以直接被调用,因此效率高 2. 嗯嗯
23 - kevinsu2019-05-15可以这样比较吗?老师 import time time1 = time.clock() empty_list = list() time2 = time.clock() diff_time = time2 - time1 print (diff_time) import time time1 = time.clock() empty_list = [] time2 = time.clock() diff_time = time2 - time1 print (diff_time)展开
作者回复: 这样可以,但是不是很准确,尤其对于简单并且运行速度很快的代码块,建议用timeit。 因为程序中还有很多因素会影响计算的时间,比如垃圾回收机制。使用timeit会自动关掉垃圾回收机制,让程序的运行更加独立,时间计算更加准确。
共 3 条评论17 - 小豹子2019-05-24看了很多留言,大部分都在讲的不对,两个时间都一样。我恰好windows,linux,jupyter都测试了下,windows和jupyter的确是时间一样,之后linux才是老师说的情况。12
- 汤尼房2019-05-15景老师,一直在想一个tuple元组如何拥有大数据量的元素,比如千万个元素、上亿个元素。因为tuple是静态的,不能添加元素,于是今天实践将[i for i in xrange(1000000000)]给初始化成tuple,发现初始化的过程相当耗时间,之前也希望利用tuple的性能比list好的优点,想把含有大数据量的list给转换成tuple来处理,今天实践发现初始化过程非常耗时间,请问景老师,平时在工作过程中遇到的含有大数据量个元素的tuple是如何形成的呢?共 1 条评论11
- 高权2019-05-23为什么我测试的元组和列表的初始化时间一样呢?共 2 条评论10
- Jared2019-05-15老师真帅。9
- Mr.Chen2019-10-10老师,“有序”应该怎么理解。
作者回复: 内部的排列是有序的,比如你遍历一遍并打印,其顺序应该和你插入元素的顺序一样
8 - kevinsu2019-05-15import timeit print(timeit.timeit('list(x for x in range(1,1000))',number=10000)) print(timeit.timeit('[x for x in range(1,1000)]',number=10000)) 0.6829426919994148 0.36637431800045306 看着是[]更快些,😄展开共 2 条评论8
- Geek_59f23e2019-05-15实测被打脸了😂函数构建和直接构建一个空列表或数组速度上并没有什么差别,有时前者快些,有时后者快些。。。 In [1]: timeit 'lst1 = []' 9.86 ns ± 0.721 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) In [2]: timeit 'lst2 = list()' 9.82 ns ± 0.43 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) In [3]: timeit 'tup1 = (,)' 9.59 ns ± 0.294 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) In [4]: timeit 'tup2 = tuple()' 9.75 ns ± 0.464 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)展开
作者回复: 你的命令有些奇怪。在程序里也应该是timeit(...),试过用文中的命令测试的结果吗? 另外你python的版本和运行环境的截图能贴一下吗?
共 3 条评论8 - 刘朋2019-05-15import timeit timeit.timeit('a=list()',number=10000) 返回 0.0006914390251040459 timeit.timeit('a=[]',number=10000) 返回 0.00018375739455223083 timeit.timeit('a=()',number=10000) 返回 0.00010870955884456635共 1 条评论7
- 播州新府2019-08-28[]比list()更快,因为调用list函数有一定的开销,而[]却没有。 这个有点像C语言中的内联函数与函数的差异(from 看 有只猪)6
- 安亚明2019-05-15老师,PYTHON学校为何要从元组和列表开始。
作者回复: 因为这是最基本的数据结构啊,学语言肯定得先了解数据结构啊
6