>[danger]序列的基本操作
1. 序列的增量赋值。`+=`和`*=`实际上调用__iadd__和__imul__方法实现就地加法和就地乘法,可变序列才有带i的方法,当序列没有i方法时,退而求其次调用__add__和__mul__方法实现非就地加法和乘法,此时会开辟新的内存空间创建新的对象,所以性能效率也会显著降低。另外,增量操作不是原子操作,如果不可变对象中包含可变对象,那么就地更改可变对象是成功的,但会抛出异常,因为整个操作是在栈中进行的,涉及到2个子操作,第一个子操作可变对象更改成功,第二个操作不可变对象赋值失败,所以不可变对象的id并未改变。
2. 对序列使用`+`和`*`
3. 切片
4. 推导式
5. 排序,序列的sort方法和内置函数sorted,如list.sort就地排序;sorted非就地排序总是返回列表。python的排序算法使用的是Timbot,这是一种自适应算法,根据原始数据的顺序特点交替使用插入排序和归并排序
6. 已排序序列支持二分查找,使用bisect.bisect(haystack, needle)实现干草垛中搜索needle,比index函数更高效。对于在一个位置插入操作,有两种方式,且后者效率更高:
--先使用bisect查找位置(左和右),再使用haystack.insert(index, needle)
--直接食用bisect.insort(haystack, needle)(同样支持左和右插入),保证序列的升序
>[danger]容器序列
list、tuple 和 collections.deque 这些序列能存放不同类型的数据。
>[danger]扁平序列
str、bytes、bytearray、memoryview 和 array.array,这类序列只能容纳一种类型。
**容器序列存放的是它们所包含的任意类型的对象的引用**,而**扁平序列里存放的是值而不是引用**。换句话说,**扁平序列其实是一段连续的内存空间**。由此可见扁平序列其实更加紧凑,但是它里面只能存放诸如字符、字节和数值这种基础类型。
序列类型还能按照能否被修改来分类。
>[success]可变序列
list、bytearray、array.array、collections.deque 和 memoryview。
>[success]不可变序列
tuple、str 和 bytes。
>[danger]## 1.List(详细参见python基本数据类型之列表与元组)
列表推导式ps:
1. python2变量泄漏问题,python3的列表推导、生成器表达式、集合推导、字典推导都有自己的局部作用域,解决了同名变量泄漏问题。
2. 列表推导同filter和map的比较:性能上列表推导高一些
--filter(函数, 可迭代的对象)循环可以迭代的对象,获取每一个元素作为函数的参数依次执行,筛选出所有Ture的元素并将元素集合返回;
--map(函数, 可迭代的对象)循环可以迭代的对象,获取每一个元素作为函数的参数依次执行,返回函数的结果组成的集合
3. 应用:
--笛卡尔积,colors=['black', 'white'], sizes = ['S','M','L'],tshirts = [(color, size) for color in colors for size in sizes];
--扑克牌
4. 只能生成列表,对比于生成器表达式可以生成列表以外的其他序列。
5. 切片,赋值的对象是一个切片,则右侧的值必须是可迭代的
>[success]~~~
>l = [range(10)]
>l[2:5] = [20:30] // 修改
>l
>[0,1,20,30,5,6,7,8,9]
>del l[5:7] // 删除
>l
>[0,1,20,30,5,8,9]
>l[3::2] = [11,22] // 每两个元素进行一次赋值
>l
>[0,1,20,11,5,22,9]
生成器表达式ps:
1. 生成器表达式初始元组或array,节省内存;
2. 笛卡尔积
>[danger]## 2.Tuple(详细参见python基本数据类型之列表与元组)
1. 用于记录
2. 元组拆包
--lax = (10,20), lat, lng = lax
3. 用`*`处理剩下的元素,`*`只能用在一个变量名前
--a, b*rest = range(5)
4. collections.namedtuple具名元组:是一个工厂函数,可用来构建一个带字段名的元组和一个有名字的类。
>[success]~~~
>Card = collections.namedtuple('Card', ['rank','suit'])
>Card //就是一个类
>
>Card._fields //_fields属性是一个包含这个类所有字段名字的元组
>('rank', 'suit')
>c= Card._make([1, '黑桃']) //_make()接收一个可迭代对象来创建类的实例,等同于Card(*[1, '黑桃'])
>Card(rank=1, suit='黑桃')
>c._asdict() //把具名元组以collections.OrderedDict形式返回
>OrderedDict([('rank', 1), ('suit', '黑桃')])
5. 切片
>[danger]## 3.array
1. 内存连续,存储的是对象而不是引用
2. 适合存储只包含数字这一种数据类型的数据集。
3. 比list更高效
4. 读取文件array.frombytes和写入文件.tofile,比文本更高效,如文件中存储的是1000万float类型数据,从文本文件中读取需要把每行文字转换成float,速度相差60倍,而写入速度相差7倍,空间也相对占用更少。
>[success]~~~
>from array import array
>from random import random
>floats = array('d', (random() for i in range(10**7)))
>floats[-1]
>0.07802343889111107
>fp = open('floats.bin', 'wb')
>floats.tofile(fp)
>fp.close()
>
>floats2 = array('d')
>fp = open('floats.bin', 'rb')
>floats2.fromfile(fp, 10**7)
>fp.close()
>floats2[-1]
>0.07802343889111107
>[danger]## 4.collections.deque双向队列(参见流畅的python)
1. 线程安全,快速从两端插入和删除
2. 可以实现基于双向队列的lru cache,即存储最近用到的数据
3. 可以指定队列大小