1.列表概述
仅仅从操作方式上看,列表像是数组和链表的结合体,除按照索引访问外,还支持插入,追加,删除等操作.完全可当做队列或者栈进行使用.如果不考虑性能问题,列表视乎是一种易用且功能完善的理想数据结构.
```python
In [1]: x= [1, 2]
In [2]: x[1]
Out[2]: 2
In [3]: x.insert(0,0) # 插入数据
In [4]: x
Out[4]: [0, 1, 2]
In [5]: x.reverse() # 反转
In [6]: x
Out[6]: [2, 1, 0]
```
queue
```python
In [7]: q = []
In [8]: q.append(1) # 在列表最后插入一个数据
In [9]: q.append(2)
In [10]: q
Out[10]: [1, 2]
In [11]: q.pop() # 清除追加顺序弹出数据
Out[11]: 2
In [12]: q.pop()
Out[12]: 1
In [13]: q
Out[13]: []
```
***
如果有大量写操作,建议使用 collections,queue 类型
***
列表的内部结构是由两部分组成,保存元素数量和内存分配计数的头部,以及储存元素指针的独立数组.所有元素项使用该数组保存指针引用,并不嵌入内容.
***
作为使用频率最高的数据结构之一,列表的性能优化很重要,固定长度的头部结构,很容易实现内存复用.创建时,有限从复用区获取.被挥手时,除非超出复用数量限制(80) ,否则会被放回服用去,而非交还内存,每次真正需要分配和释放的是指针数组.
用数组而非链表存储元素项引用,也有实际考虑.从读操作开看,无论遍历还是基于序号访问,数组性能总是最高的.尽管插入,删除,等变更操作需要移动内存,但也仅仅是指针复制,无论元素大小,不会有太高消耗,如果列表太大,或者写操作多余读,那么应该使用针对性的数据结构操作.
***
2.构建
显示指定元素构建语法最为常用,也可基于创建类型,接受可迭代对象作为初始内容,不同于数组,列表仅存储指针,而对元素内容毫不关心,如此,可以是不同类型混合.
```python
In [14]: [1,"abc",3.14]
Out[14]: [1, 'abc', 3.14]
In [16]: list("abc")
Out[16]: ['a', 'b', 'c']
In [17]: list(range(3))
Out[17]: [0, 1, 2]
```
另外有被称之为列表推导式的语法,同样适用括号,但是以for循环初始化元素,并且可以选择if作为过滤条件.
```python
In [1]: class A(list):
...: pass
...:
In [2]: type(A('abc')+ list('del')) # 返回的是list而不是a
Out[2]: list
In [3]: class B(collections.UserList):
...: pass
In [4]: type(B("abc") + list("del")) # 返回了B类型
Out[4]: __main__.B
```
***
最小接口设计是一个基本原则,应该慎重考虑这种功能的类型是否适合作为基类.
3.操作
用加法运算符链接多个列表,乘法赋值内容
```python
In [9]: [1, 2] + [3, 4]
Out[9]: [1, 2, 3, 4]
In [10]: [1, 2] * 2
Out[10]: [1, 2, 1, 2]
```
注意,同时加法(或者减法) 运算,但是结果可能会不同.
```python
In [12]: a = [1, 2]
In [13]: b = a
In [14]: a = a + [3, 4] # 新建列表对象,然后和a关联
In [15]: a
Out[15]: [1, 2, 3, 4] # a,b结果不同,确定a指向新对象
In [16]: b
Out[16]: [1, 2]
In [17]: a = [1, 2]
In [18]: b = a
In [19]: a += [3, 4] # 直接修改了a的内容
In [20]: a
Out[20]: [1, 2, 3, 4]
In [21]: b # b的内容也随着更改
Out[21]: [1, 2, 3, 4]
```
> 编译器将"+=" 运算符处理成INPLACE_ADD操作,也就是修改原函数,而并非建立新对象,其中效果类似于list.extend 方法
判断元素是否存在,习惯用in,而并非index()方法
```python
in[22]: 2 in [1, 2]
Out[22]: True
```
至于删除操作,可用索引序号指定单个元素,或者切片指定删除范围.
```python
In [23]: a = [0, 1, 2, 3, 4, 5]
In [24]: del a[5] # 删除单个元素
In [25]: a
Out[25]: [0, 1, 2, 3, 4]
In [26]: del a[1:2] # 删除范围元素
In [27]: a
Out[27]: [0, 2, 3, 4]
```
返回切片时创建新列表对象,并且复制相关指针数据到新数组,出所引用目标相同之外,列表自身的修改(增加,删除) 互不影响
```python
In [32]: a = [0, 2, 4 ,6]
In [33]: b = a[:2] # 复制引用
In [34]: b
Out[34]: [0, 2]
In [35]: a[0] is b[0]
Out[35]: True
In [36]: a.insert(1,1) # 对a列表操作,不会影响b
In [37]: a
Out[37]: [0, 1, 2, 4, 6]
In [38]: b
Out[38]: [0, 2]
```
***
复制的是指针(引用),而并非目标元素对象.
对列表自身的修改互补影响,但是对目标元素对象的修改是共享的
***
### 3.列表排序可以设定条件,比如按照字段或者长度等
```python
In [55]: d = [3,0,2,1]
In [56]: sorted(d) # 同样可以指定排序条件,或者倒叙
Out[56]: [0, 1, 2, 3]
In [57]: d
Out[57]: [3, 0, 2, 1]
```
4.利用bisect模块,可向有序列表插入元素,它使用二分法查找合适位置,可以实现优先级队列或者一致性哈希算法
```python
In [59]: import bisect
In [60]: bisect.insort_left(d,1) # 插入新的元素后,依旧保持有序状态
In [61]: d
Out[61]: [0, 1, 2, 4]
In [62]: bisect.insort_left(d,2)
In [63]: d
Out[63]: [0, 1, 2, 2, 4]
In [64]: bisect.insort_left(d,3)
In [65]: d
Out[65]: [0, 1, 2, 2, 3, 4]
```
***
自定义复合类型,可通过重载比较运算符(__eq__,__lt__ 等) 实现自定义排序条件.
领取专属 10元无门槛券
私享最新 技术干货