序列類型的劃分:
第一種劃分:
- 容器序列:能夠存放不一樣類型的數據,存放的是引用算法
- 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)