序列构成的数组

序列类型的划分:

  第一种划分:

    - 容器序列:能够存放不一样类型的数据,存放的是引用算法

      - list、tuple、collections.deque数组

    - 扁平序列:只能存放一种类型的数据,存放的是值安全

      - str、bytes、bytearray、memoryview、array.arrayapp

  第二种划分:

    - 可变序列:内容能够改变dom

      - list、bytearray、array.array、collections.deque、memoryview函数

    - 不可变序列ui

      - tuple、str、bytesspa

 列表推导同filter和map的比较

  - filter和map合起来能作的事情,列表推导也能作,并且还不须要借助难以理解和阅读的lambda表达式线程

from  collections import abc s = 'abcdefg'

# 列表推导
l1 = [ord(x) for x in s if ord(x)>99] print(l1) # map返回的是一个map object,它是一个Iterator
map_object = map(ord, s) print(isinstance(map_object,abc.Iterator)) # map和filter结合
l2 = list(filter(lambda x: x > 99, map_object)) print(l2)

输出:

[100, 101, 102, 103]
True
[100, 101, 102, 103]code

 生成器表达式

  生成器表达式背后遵循了迭代器协议,能够逐个地产出元素,而不是先创建一个完整的列表,而后再把这个列表传递到某个构造函数里。

  生成器表达式语法和列表推导差很少,只不过把方括号换成圆括号而已

 

import array symbols = 'aeiou'

# 用生成器构造tuple
t = tuple(ord(x) for x in symbols) print(t) print('-' * 100) # 用生成器构造array
a = array.array('I',(ord(x) for x in symbols)) print(a) print('-' * 100) # 生成器产生笛卡尔积
colors = ['black','white'] size = ['S','M','L'] for tshirt in ('{0} {1}'.format(c,s) for c in colors for s in size): print(tshirt)

输出:

(97, 101, 105, 111, 117)
----------------------------------------------------------------------------------------------------
array('I', [97, 101, 105, 111, 117])
----------------------------------------------------------------------------------------------------
black S
black M
black L
white S
white M
white L

 

 

元组拆包

  在一行语句内把元组分别赋值给多个变量

import os # 元组拆包常规操做
person = ('Alice',20) name,age = person print('name is',name,'age is',age) print('-' * 100) # 使用“_”占位符
_,filename = os.path.split("D\Program Files\Test.doc") print('filename =',filename) print('-' * 100) # 使用*占位符
address = ('China', 'ZheJiang', 'HangZhou',310000) _,province,*other,zipcode = address print('province =',province,', zipcode = ',zipcode) print('-' * 100) # 嵌套拆包
numbers = (('one',1),('two',2),('three',3)) for (name, value) in numbers: print(name,'=',value)

输出:

name is Alice age is 20
----------------------------------------------------------------------------------------------------
filename = Test.doc
----------------------------------------------------------------------------------------------------
province = ZheJiang , zipcode = 310000
----------------------------------------------------------------------------------------------------
one = 1
two = 2
three = 3

 具名元组

  collections.namedtuple是一个工厂函数,它能够用来构建一个带字段名的元组,这个带字段名的元组的行为模式就像一个类

from collections import namedtuple,OrderedDict # 使用namedtuple定义一个Country类
Country = namedtuple('Country','name_and_abbr area population') china = Country(('China','CN'),960,13) print(china) print('-' * 20,'用.号访问Country类的属性','-' * 20) # 用.号访问Country类的属性
print('china.population=',china.population) name,abbr = china.name_and_abbr print('name='+name,'abbr='+abbr) print('-' * 20,'用[]访问Country类的属性','-' * 20) # 也能够用[]访问Country类的属性
print('china[0]=',china[0]) print('-' * 20,'Country类的_fileds方法','-' * 20) # Country类的_fileds方法返回它的字段
print('Country._filds =',Country._fields) print('-' * 20,'Country类的_make方法','-' * 20) # Country类的_make方法构造一个实例
japan1 = Country._make((('Japan','JP'),97.8,1.26)) print(japan1) # 和调用构造函数效果相同:
japan2 =Country(*(('Japan','JP'),97.8,1.26)) print(japan2) print('-' * 20,'Country类的_asdict方法','-' * 20) # Country类的_asdict方法把具名元组以collections.OrderedDict的形式返回
print('china._asdict() is OrderedDict:',isinstance(china._asdict(),OrderedDict)) for name,value in china._asdict().items(): print(name,'=',value)

输出:

Country(name_and_abbr=('China', 'CN'), area=960, population=13)
-------------------- 用.号访问Country类的属性 --------------------
china.population= 13
name=China abbr=CN
-------------------- 用[]访问Country类的属性 --------------------
china[0]= ('China', 'CN')
-------------------- Country类的_fileds方法 --------------------
Country._filds = ('name_and_abbr', 'area', 'population')
-------------------- Country类的_make方法 --------------------
Country(name_and_abbr=('Japan', 'JP'), area=97.8, population=1.26)
Country(name_and_abbr=('Japan', 'JP'), area=97.8, population=1.26)
-------------------- Country类的_asdict方法 --------------------
china._asdict() is OrderedDict: True
name_and_abbr = ('China', 'CN')
area = 960
population = 13

 切片

  在切片和区间操做里不包含区间范围的最后一个元素

l = [10,20,30,40,50,60] print('l[:2] =',l[:2]) print('l[2:] =',l[2:])

输出:

l[:2] = [10, 20]
l[2:] = [30, 40, 50, 60]

   使用slice对切片进行命名

people = '''person1 20 175 person2 30 163 person3 25 182 ''' name = slice(0,7) age = slice(8,10) height = slice(11,14) for item in people.split("\n"): print('name:',item[name]) print('age:',item[age]) print('height:',item[height]) print('-' * 100)

输出:

name: person1
age: 20
height: 175
----------------------------------------------------------------------------------------------------
name: person2
age: 30
height: 163
----------------------------------------------------------------------------------------------------
name: person3
age: 25
height: 182
----------------------------------------------------------------------------------------------------

   给切片赋值

    若是把切片放在赋值语句的左边,或把它做为del操做的对象,咱们就能够对序列进行嫁接、切除或就地修改操做

l = list(range(1,11)) print('l:',l) # 把l的第9和10项替换成100

print('-' * 20,'把l的第9和10项替换成100','-' * 20) l[8:10] = [100] print(l) print('-' * 20,'把l的第1,3,5,7,9项替换成95,96,97,98,99','-' * 20) # 把l的第1,3,5,7,9项替换成95,96,97,98,99
 l[::2] = [95,96,97,98,99] print(l) # 删除l的第2,4,6,8项

print('-' * 20,'删除l的第2,4,6,8项','-' * 20) del l[1::2] print(l)

输出:

l: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
-------------------- 把l的第9和10项替换成100 --------------------
[1, 2, 3, 4, 5, 6, 7, 8, 100]
-------------------- 把l的第1,3,5,7,9项替换成95,96,97,98,99 --------------------
[95, 2, 96, 4, 97, 6, 98, 8, 99]
-------------------- 删除l的第2,4,6,8项 --------------------
[95, 96, 97, 98, 99]

 对序列使用+和*

  +和*都是对序列进行拼接,在拼接的过程当中,两个被操做的序列都不会被修改,Python会创建一个包含一样类型数据的序列来做为拼接的结果

  *操做把一个序列复制几份而后拼接起来,但这里使用浅copy,对于嵌套结构须要小心

def print_split(s): print('-' * 20, s, '-' * 20) # 拼接使用浅copy # 使用基本类型没有影响
print_split('使用基本类型没有影响') l1 = [1] print('id of l1[0]:', id(l1[0])) # 对l1中的元素进行复制,而后拼接 # l是由两个整数构成的list
l = l1 * 2
print(l) for item in l: print(id(item)) # 不会影响l[1]
l[0]=2
print(l) # 使用对象有反作用
print_split('使用对象有反作用') l2=[['_']] print('id of l2[0]:',id(l2[0])) # 对l2中的元素进行复制,而后拼接 # l是由两个list构成的list
l = l2*2
for item in l: print(id(item)) # 会影响l[1][0]
l[0][0]='a'
print(l)

输出:

-------------------- 使用基本类型没有影响 --------------------
id of l1[0]: 140734998434848
[1, 1]
140734998434848
140734998434848
[2, 1]
-------------------- 使用对象有反作用 --------------------
id of l2[0]: 1171703476616
1171703476616
1171703476616
[['a'], ['a']]

   创建嵌套列表的一个例子

def print_split(s): print('-' * 20, s, '-' * 20) # 创建由列表组成的列表
print_split('创建由列表组成的列表') # 错误的创建方式:会把相同列表复制三次
print_split('错误的创建方式:会把相同列表复制三次') board = [['_'] * 3] * 3
print(board) board[0][0]='a'
print(board) # 正确的创建嵌套列表方式:
print_split('正确的创建嵌套列表方式') board = [['_']*3 for i in range(3)] print(board) board[0][0]='a'
print(board)

输出:

-------------------- 创建由列表组成的列表 --------------------
-------------------- 错误的创建方式:会把相同列表复制三次 --------------------
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
[['a', '_', '_'], ['a', '_', '_'], ['a', '_', '_']]
-------------------- 正确的创建嵌套列表方式 --------------------
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
[['a', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

 

list.sort方法和内置函数sorted

  不一样点:

    list.sort方法就地排序列表,返回None

    sorted方法返回一个新建的排好序的列表

  相同点:

    接受参数相同

    reverse:若是被设定为True,序列以降序输出

    key:一个只有一个参数的函数,被用在序列里的每个元素上,所产生的结果将是排序算法依赖的对比关键字

fruits = ['grape','raspberry','apple','banana'] print('sorted(fruits):',sorted(fruits)) # 原列表并未被改变
print('fruits:',fruits) print('sorted(fruits,reverse=True):',sorted(fruits,reverse=True)) print('sorted(fruits,key=len):',sorted(fruits,key=len)) print('list.sort(fruits):',list.sort(fruits)) # 原列表被改变了
print('fruits:',fruits)

输出:

sorted(fruits): ['apple', 'banana', 'grape', 'raspberry']
fruits: ['grape', 'raspberry', 'apple', 'banana']
sorted(fruits,reverse=True): ['raspberry', 'grape', 'banana', 'apple']
sorted(fruits,key=len): ['grape', 'apple', 'banana', 'raspberry']
list.sort(fruits): None
fruits: ['apple', 'banana', 'grape', 'raspberry']

 bisect管理已排序的序列

  bisect模块包含两个主要函数:bisect和insort,它们都利用二分查找算法来在有序序列中查找或插入元素

  bisect函数实际上是bisect_right函数的别名,后者还有一个姊妹函数叫bisect_left,它们的区别在于,bisect_left返回的插入位置是序列中全部与插入元素相同的元素的前面,而bisect_right则是后面

  与bisect类似,insort有一个变体叫insort_left,差别与bisect和bisect_left类似

from random import randint from bisect import bisect,insort l = [randint(0,20) for i in range(10)] list.sort(l) print('l:',l) x = randint(0,20) print('x:',x) # 查找插入位置
print('position to insert x:',bisect(l,x)) # 进行插入
insort(l,x) print('l:',l)

输出:(输出随机改变)

l: [7, 8, 9, 12, 13, 13, 14, 17, 18, 18]
x: 2
position to insert x: 0
l: [2, 7, 8, 9, 12, 13, 13, 14, 17, 18, 18]

from bisect import bisect,insort def grade(score,breakpoints=[60,70,80,90],grades='FDCBA'): pos = bisect(breakpoints,score) return grades[pos] print([grade(score) for score in [33,99,77,70,89,90,100]])

输出:
['F', 'A', 'C', 'C', 'B', 'A', 'A']

 

数组

  若是咱们须要一个只包含数字的列表,那么array.array比list更高效

  数组支持全部跟可变序列有关的方法,好比.pop .insert ,extend

  另外,数组还提供从文件读取和存入文件的更快的方法:.fromfile 和 .tofile

  数组第一个参数是数组存放的元素类型

  

from array import array from random import random # 创建一个double构成的数组,一共10^6个元素
arr = array('d',(random() for i in range(10**6))) # 把数组放进文件
with open('floats.bin','wb') as fp: arr.tofile(fp) # 打印数组最后一个元素
print(arr[-1]) # 新建一个double数组
floats = array('d') fp = open('floats.bin','rb') # 从文件读取数据,构造数组
floats.fromfile(fp,10**6) # 打印数组最后一个元素
print(floats[-1])

输出(随机输出):

0.608500026173036
0.608500026173036

 

内存视图

  memoryview让用户在不复制内容的状况下操做同一个数组的不一样切片

  能用不一样的方式读写同一块内存数据,并且内容字节不会随意移动

from array import array # 定义一个以两个字节带符号整数构成的数组
num = array('h',[-2,-1,0,1,2]) # 用array构造memoryview
mv2 = memoryview(num) # memoryview的长度是根据其解析类型来的
print('len(mv):',len(mv2)) # 对元素的解析也是根据其解析类型来的
print('mv[0]:',mv2[0]) # 换一种解析类型,用一个字节来解析
mv1 = mv2.cast('B') # 打印用一个字节来解析的内容
print(mv1.tolist()) # 把第6个字节替换成00000100,注意,每一个字的高低位字节是倒过来显示的
mv1[5] = 4

# 会影响到原先的memoryview
print(mv2.tolist())

输出:

len(mv): 5
mv[0]: -2
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
[-2, -1, 1024, 1, 2]

 

双端队列

  删除列表的第一个元素之类的操做是很耗时的  

  collections.deque类是一个线程安全,能够快速从两端添加或者删除元素的数据类型

from collections import deque # 定义一个长度为10的双端队列 # 用0-9填充
dq = deque(range(10),maxlen=10) print('dq:',dq) # rotate参数是正数,右放到左;
dq.rotate(3) print('dq.rotate(3):',dq) # rotate参数是负数,左放到右
dq.rotate(-3) print('dq.rotate(-3):',dq) # deque能够在两端添加元素,但另外一端的元素会被挤出
dq.append(10) print('deque.append(10):',dq) dq.appendleft(0) print('dq.appendleft(0):',dq) # deque也能够在两端添加可迭代对象
dq.extend([11,12]) print('dq.extend([11,12]):',dq) # 注意,deque是一个一个添加元素的,因此在左端添加可迭代对象时,顺序是倒过来的
dq.extendleft([1,0]) print('dq.extendleft([1,0]):',dq) # deque能够在两端删除元素,但不能带参数
a = dq.pop() print('dq.pop():',a) print('dq after pop:',dq) a = dq.popleft() print('dq.popleft():',a) print('dq after pop:',dq)

输出:

dq: deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)dq.rotate(3): deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)dq.rotate(-3): deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)deque.append(10): deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], maxlen=10)dq.appendleft(0): deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)dq.extend([11,12]): deque([2, 3, 4, 5, 6, 7, 8, 9, 11, 12], maxlen=10)dq.extendleft([1,0]): deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)dq.pop(): 9dq after pop: deque([0, 1, 2, 3, 4, 5, 6, 7, 8], maxlen=10)dq.popleft(): 0dq after pop: deque([1, 2, 3, 4, 5, 6, 7, 8], maxlen=10)

相关文章
相关标签/搜索