容器序列:list,tuple,collections.deque (能存放不一样类型)html
扁平序列:str,bytes,bytearray,memoryview,array.arraypython
▲ 容器序列存放的是所包含的任意类型的对象引用。算法
可变序列:list,bytearray,memoryview,array.array,collection.deque编程
不可变序列:str,tuple,bytes数组
2.一、列表推导和生成器表达式安全
列表推导(listcomps)是构建列表的快捷方式,一般原则是只用列表推导来建立新的列表。网络
生成器表达式(genexps)用来建立其余类型的序列。app
>>> x = 'ABC' >>> dummy = [ord(x) for x in x] >>> x 'ABC' >>> dummy [65,66,67]
▲ Python3 中的列表推导式、生成器表达式、集合推导、字典推导都有本身的局部做用域。表达式内部的变量和赋值只在局部做用域生效。dom
列表推导能够帮助咱们把一个序列或是其余可迭代类型中的元素进行过滤或是加工,而后再新建一个列表。异步
2.二、列表推导同 filter 和 map 比较
>>> x = 'ABCDEF' >>> dummy = [ord(x) for x in x if ord(x)>66] >>> dummy [66,67,68,69,70] >>> dummy = list( filter(lambda c:c>66,map(ord,x)) ) >>> dummy [66,67,68,69,70]
2.三、生成器表达式
生成器表达式遵照迭代器协议,能够逐个产出元素,而不是先创建一个完整的列表。
▲ 生成器表达式的语法和列表推导差很少,只是把方括号改为圆括号!
colors = ['black','white'] sizes = ['S','M','L'] for tshirt in ('%s %s'%(c,s) for c in colors for s in sizes): print(tshirt)
3.一、元组的拆包
元组除了用做不可变的列表,它还能够用于没有字段名的记录
元组的拆包形式之一(平行赋值)
>>> scores = (93,97) >>> CN,EN = scores #元组拆包 >>> CN 93 >>> EN 97
不使用中间变量交换元素
>>> a,b = b,a
用 * 运算符把 可迭代对象 拆开做为函数的参数
>>> t = (20,8) >>> divmod(*t) (2,4)
让函数用元组的形式返回多个值
>>> import os >>> _,filename = os.path.split('/home/abc.py') >>> filename abc.py
_ 占位符能帮助处理不感兴趣的数据。
用 * 号处理剩下的元素(这个变量能够放在赋值表达式的任意位置)
>>> a,b,*rest = range(5) >>> a,b,rest (0,1,[2,3,4]) >>> a,*body,b,c = range(5) >>> a,*body,b,c (0,[1,2],3,4)
嵌套元组的拆包
class1 = [ ('xiaoming','Boy',(85,88,90)), ('xiaohong','Girl',(90,88,90)), ] for name,sex,scores in class1: print(name,sex,scores)
3.二、具名元组
collections.namedtuple 是一个工厂函数,用来建立一个带字段名的元组和一个有名字的类。
建立一个具名元组须要两个参数,一个是类名,另外一个是类的各个字段的名字。
能够是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串
>>> from collections import namedtuple >>> City = namedtuple('City','name country population coordinates') # <class '__main__.City'> >>> tokyo = City('Tokyo','JP',38.32,(35.68872,139.25436)) >>> tokyo City(name='Tokyo', country='JP', population=38.32, coordinates=(35.68872, 139.25436)) >>> tokyo.population 38.32 >>> tokyo[0] 'Tokyo'
具名元组还具备本身专有属性:_fields类属性,类方法_make(iterable),实例方法_asdict()
>>> City._fields ('name', 'country', 'population', 'coordinates') >>> LatLong = namedtuple('LatLong','lat long') >>> delhi_data = ('Delhi NCR','IN',32.21,LatLong(28.45721,76.89342)) >>> delhi = City._make(delhi_data) # 生成实例相似 City(*delhi_data) >>> delhi._asdict() OrderedDict([('name', 'Delhi NCR'), ('country', 'IN'), ('population', 32.21), ('coordinates', LatLong(lat=28.45721, long=76.89342))])
4.一、切片
在切片和区间操做里不包含区间范围的最后一个元素。这样带来的好处有:
● 当只有一个位置信息时,咱们也能够快速看出切片和区间里有几个元素:range(3) 和 my_list[:3] 都返回3个元素。
● 当起止位置均可见时,能够计算出切片和区间的长度(stop - start )
● 利用任意一个下标把序列分割成不重叠的两部分。my_list[:x] 和 my_list[x:]
4.二、对对象进行切片
对 seq[start:stop:step] 进行求值的时候,Python会调用 seq.__getitem__(slice(start,stop,step))
>>> HTML = """ ... 文本内容 """ >>> TEXT_HEAD = slice(0,23) >>> IMG_URL = slice(23,56) >>> for item in HTML: print(item[TEXT_HEAD],item[IMG_URL])
▲ 若是赋值的对象是一个切片,那么赋值语句的右侧必须是个可迭代对象。
>>> li = list(range(10)) >>> li[2:5] = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'range' object does not support item assignment >>> li[2:5] = [100]
+ 号两侧的序列由同类型的数据所构成,在拼接的过程当中,两个被操做的序列都不会被修改。
=》 Python会新建一个包含同类型数据的序列来做为拼接的结果。
▲ 在 a * n 语句中,若是序列a里的元素是对其余可变对象的引用,获得的列表里包含的3个元素实际上是3个引用。
>>> my_list = [[]] * 3 >>> my_list [[], [], []] >>> print(id(my_list[0]),id(my_list[1]),id(my_list[2])) 1767860956104 1767860956104 1767860956104 >>> my_list = [[''] *3 for i in range(3) ] >>> print(id(my_list[0]),id(my_list[1]),id(my_list[2])) 1767860947400 1767860945992 1767860953544
增量赋值运算符 += 和 *= 利用的特殊方法是 __iadd__ (就地加法)和 __imul__,可是若是没有实现 __iadd__ 和 __imul__ 的话,
a += b 效果就变成了 a = a + b,首先计算 a + b,获得一个新的对象,而后赋值给 a。
可变序列通常都实现了 __iadd__ 和 __imul__
一个罕见的边界状况:
>>> t = (1,2,[3,4]) >>> t[2] += [5,6] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> t (1, 2, [3, 4, 5, 6])
▲ 不要把可变对象放在元组里面。
▲ 增量赋值不是一个原子操做。
▲ Python 运行原理可视化分析工具 → http://www.pythontutor.com/visualize.html#mode=edit
6.一、list.sort 方法和内置函数 sorted()
list.sort 方法会就地排序列表,返回None值。
sorted() 方法会新建一个列表做为返回值。
list.sort 和 sorted函数,都有两个可选的关键字参数。
reverse :被设定为 True,被排序的列表的元素会以降序输出。
key:一个只有一个参数的函数,这个函数会被用在序列里的每个元素上,所产生的结果将是排序算法依赖的对比关键字,如key=len
key参数也能够对一个混有数字字符和数值的列表进行排序。
>>> l = [1,7,3,'2','6',8] >>> sorted(l,key=int) >>> sorted(l,key=str)
6.二、用bisect来管理已排序的序列
bisect包含两个主要函数,bisect 和 insort,都利用二分查找算法在有序序列中查找或插入元素。
bisect 的表现能够从两个方面进行:
def grade(score,breakpoint=[60,70,80,90],grade='FDCBA'): i = bisect.bisect(breakpoint,score) return grade[i]
7.一、当列表不是首选时
若是咱们须要一个只包含数字的列表,那么array.array 比 list 更加高效。
建立数组须要一个类型码,类型码用来表示在底层的C语言应该存放怎样的数据类型。
类型代码 | C类型 | Python类型 | 最小大小(以字节为单位) |
---|---|---|---|
'b' |
signed char | INT | 1 |
'B' |
unsigned char | INT | 1 |
'u' |
Py_UNICODE | Unicode字符 | 2 |
'h' |
signed short | INT | 2 |
'H' |
unsigned short | INT | 2 |
'i' |
签名int | INT | 2 |
'I' |
无符号整数 | INT | 2 |
'l' |
signed long | INT | 4 |
'L' |
无符号长整数 | INT | 4 |
'q' |
signed long long | INT | 8 |
'q' |
无符号long long | INT | 8 |
'f' |
float | float | 4 |
'd' |
double | float | 8 |
数组还提供从文件读取和存入文件的更快的方法。
from array import array from random import random floats = array('d',(random() for i in range(10**7))) print(floats[-1]) 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()
▲ 数组的排序:a = array.array(a.typecode, sorted(a))
7.二、内存=视图
memoryview 是一个内置类,能在不复制内容的状况下操做同一个数组的不一样切片。
a = bytearray('aaaaaaa',encoding='utf8') b = a[:2] b[:2] = b'bb' print(a,b) # bytearray(b'aaaaaaa') bytearray(b'bb') ma = memoryview(a) mb = ma[:2] mb[:2] = b'bb' print(ma.tobytes(),mb.tobytes()) # b'bbaaaaa' b'bb'
使用场景是网络程序中socket接收和接收数据的解析
7.三、双向队列和其余形式的队列
collections.deque 类是一个线程安全,能够快速从两端添加或者删除元素的数据类型。
>>> from collections import deque >>> dq = deque(range(10),maxlen=10) >>> dq deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10) >>> dq.rotate(3) # 当n>0时,最右边n个元素移到最左边,当n<0时,最左边移到最右边 >>> dq deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10) >>> dq.rotate(-4) >>> dq deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10) >>> dq.appendleft(-1) # 对已满的队列添加元素时,尾部元素会被删除 >>> dq deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10) >>> dq.extend([11,22,33]) >>> dq deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10) >>> dq.extendleft([10,20,30,40]) >>> dq deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8], maxlen=10)
其余形式的队列:
queue:不一样的线程能够利用这些数据类型交换信息。
multiprocessing:实现了本身的Queue,设计给进程间通讯用的。
asyncio:为异步编程里的任务提供。
heapq:把可变序列当作堆队列或者优先队列使用。