流畅的python(一)序列构成的数组
1、内置序列类型概览
按照存放类型分类
- 不同类型的数据:
list, tuple, collections.deque
- 一种类型的数据:
str, bytes, bytearray, memoryview
和arrray.array
按照是否修改分类
- 可变序列:
list, bytearray, array.array, collections.deque
和memoryview
- 不可变序列:
tuple, str
和bytes
2、列表推导和生成器表达式
[i for i in range(10)] 是构建列表的快捷方式
生成器表达式
生成器表达式背后遵守迭代器协议,可以逐个地产出元素,显然节省内存,生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号。
(i for i in range(10))
symbols = '$#@%^&*' a = tuple(ord(s) for s in symbols if ord(s) > 35) print(a) import array a = array.array('I',(ord(s) for s in symbols)) print(a) colors = ['b','w'] sizes = ['S','M','L'] for i in ('%s,%s'%(color,size) for color in colors for size in sizes): print(i)
3、元组不仅仅是不可变的列表
用元组作为字段
元组拆包
元组其实是对数据的记录:元组中的元素存放了数据和位置
可以当成记录加以利用
拆包
a,b = b,a
- 平行赋值
>>> x = (6, 9)
>>> a, b = x
>>> a
6
>>> b
9
- 用
*
拆开作为函数参数
>>> t = (20, 8)
>>> divmod(*t)
(2, 4)
- 用
*
处理剩下的元素,可以出现在赋值表达式任意位置
>>> a, b, *rest = range(5)
""" 记录 拆包 """ lax_coordinates = (33.9425,-118.408056) city,year,pop,chg,area = ('Tokyo',2003,32450,0.66,8014) traveler_ids = [('USA','2345633'),('CHINA','ER5556'),('BRA','782829')] for passport in sorted(traveler_ids): print('%s/%s'%passport) for country,_ in traveler_ids: print(country) a = (20,8) c,d = divmod(*a) print(c,d) import os a = os.path.split("/home/www/ddd/ccc.pub") print(a) #*用来处理剩下来的元素 a,*b,rest = range(10) print(a,b,rest) #嵌套元组拆包 metro_areas = [('Tokyo','JP',36.33,(35.998877,139.887665)), ('De NCR','IN',21.334,(28.61555,77.20999)), ('Mexico city','MX',20.14,(19.2345,-99.8765)), ('Sao Paulo','BR',19.887,(-23.8887,-46.65533))] print('{:15}|{:^9}|{:^9}'.format('City','lat.','long.')) fmt = '{:15}|{:9.4f}|{:9.4f}' for name,cc,pop, (latitude,longitude) in metro_areas: if longitude <= 0: print(fmt.format(name,latitude,longitude)) #具名元组 from collections import namedtuple City = namedtuple('City','name country population coordinates') tokyo = City('Tokyo','JP',36,(35,139)) print(tokyo) print(City._fields) a = (2,3,4,45,6,9) print(a[::3]) t = (1,2,[3,4]) t[2] += [5,6] print(t)
4、切片
切片
l[::-2]
l[:5] = []
5、对序列使用+和*
>>> [[0] * 3] * 3 [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>> [[0] * 3 for i in range(3)] [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
第一种,外面的列表包含了3个指向同一个列表的引用,修改一个,其他位置也会修改
6、序列的增量赋值
序列的增量赋值
_iadd
:就地加法(+=) _add
m = l*5
m += [1,2]
7、list.sort方法和内置函数sorted
list.sort
方法会就地排序列表,也就是说不会把原列表复制一份。
两个关键词参数:reverse
,key
8、已排序搜索和插入bisect
#比较有趣的用法 def grade(score,breakpoints = [60,70,80,90],grades = 'FDCBA'): i = bisect.bisect_right(breakpoints,score) return grades[i] print([grade(score) for score in [33,60,62,69,80,100]]) #已排序队列的插入 bisect.insort_left([],10)
9、当列表不是首选时
数组(array.array)
from array import array from random import random floats = array('d',(random()*100 for i in range(10**7))) print(floats[-1]) #注意哦,数组里面存的是数字的字节表达 fp = open('floats.bin','wb') floats.tofile(fp) fp.close()
内存视图memoryview
泛化和去数学化的NumPy数组,实现在数据结构之间共享内存。用以处理大型数据集合
注意共享内存的意思是对memoryview的操作不会产生新的对象!!!这也是其高效的原因
NumPy 与 SciPy
from time import perf_counter as pc t0 = pc() floats = numpy.loadtxt('data.txt') t1 = pc() floats /= 3 t2 = pc() numpy.save('floats-10M',floats) t3 = pc() floats2 = numpy.load('floats-10M.npy','r+') t4 = pc() floats2 *=363 t5 = pc() {'t0': 0.851668039, 't1': 153.021685987, 't2': 153.038698158, 't3': 153.4188989, 't4': 153.420616467, 't5': 153.455011833}
读取txt和二进制文件简直天壤之别,当然这有NumPy优化内存映射机制
还有 deque heapq
....
from collections import deque dq = deque(range(10),maxlen = 10) dq.rotate(-4) print(dq) dq.pop() print(dq) dq.extend([11,12,13]) print(dq)
queue
import queue
#用以同步线程安全,满员时会等待销毁后再执行
multiprocessing
import multiprocessing
#用以同步进程管理,同queue
asyncio
import asyncio
#是用来编写 并发 代码的库,使用 async/await 语法
heapq
import heapq
#将可变序列当做堆队列处理