序列構成的數組

序列類型的劃分:

  第一種劃分:

    - 容器序列:能夠存放不一樣類型的數據,存放的是引用算法

      - 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)

相關文章
相關標籤/搜索