问题背景
列表(list)是Python中最基本的内置数据类型之一,从语言的早期版本开始就存在。随着时间的推移,它们的内部结构得到了改进,特别是为了提高性能和编程的便利性。
问题
重要的是要理解,Python中的列表并不是作为链表实现的,而是作为动态数组实现的。错误的理解会导致不高效的代码或错误的操作复杂性计算。
解决方案
列表被实现为动态数组,它们在需要时"跳跃式"地增加已分配内存的大小(扩展),以避免在添加元素时的持续开销。这允许在列表末尾以摊销的O(1)时间插入和删除元素。在中间/开头插入或删除需要移动元素,这需要O(n)时间。
代码示例:
my_list = [1, 2, 3] my_list.append(4) # 添加到末尾 my_list.insert(1, 'a') # 按索引插入 print(my_list)
关键特性:
可以认为Python中的list是C中的数组吗?有什么区别?
不可以,C中的数组包含固定类型的元素,顺序存放在内存中。Python list是一个指向对象的指针数组,每个指针引用一个堆中任意类型的独立对象。
如果在循环中将元素插入列表的开头会发生什么?这快吗?
不,这很慢:每次在开头插入(位置0)时,所有现有元素都会向右移动。运算的摊销复杂度为O(n),对于大列表来说会导致性能下降。
运算符+和append/extend对于列表有什么区别?
+会创建一个新列表,而不改变旧列表。append将元素添加到原始列表的末尾。extend将另一个序列中的所有元素添加到列表中,从而改变对象本身。
lst1 = [1, 2] lst2 = [3, 4] lst3 = lst1 + lst2 # lst3是新列表 lst1.append(lst2) # lst1变为[1, 2, [3, 4]] lst1.extend(lst2) # lst1变为[1, 2, 3, 4],如果lst1在上次append后未重置
在一个项目中,用list来存储和不断删除前面的元素。在大量数据时发现显著的减速。
优点:
缺点:
在发现问题后,将list替换为collections.deque,后者对于这样的操作进行了优化。
优点:
缺点: