《python中的集中列表類型總結》

一、list
list:是Python內置的一種數據類型是列表,它是一種有序的集合,可以隨時添加和刪除其中的元素。list中的元素是按照順序排列的,構造list非常簡單,按照上面的代碼,直接用 [ ] 把list的所有元素都括起來,就是一個list對象。通常,我們會把list賦值給一個變量,這樣,就可以通過變量來引用list

L = ['adam', 95.5, 'lisa', 85, 'bart', 59]
print (L)

這裏寫圖片描述
由於Python是動態語言,所以list中包含的元素並不要求都必須是同一種數據類型,我們完全可以在list中包含各種數據

L = ['Michael', 100, True]

因爲list是一個有序集合,那麼我們就可以通過下標的方式訪問裏邊的元素(下標是從0開始的的)

L = ['adam', 95.5, 'lisa', 85, 'bart', 59]
print (L[0])

這裏寫圖片描述
List下標可以是負數,-1表示最後一個元素,-2,-3一次表示倒數第二和倒數第三個元素

L = [95.5, 85, 59]
print (L[-1])
print (L[-2])
print (L[-3])

注意:當訪問的下標越界時就會報錯,比如L[-4],這時候會報錯

如果想向list中添加元素,則可以使用append()函數(插入的位置爲末尾)。要想插入到指定位置,則使用insert()方法

L = ['Adam', 'Lisa', 'Bart']
L.append('shulv')
L.insert(2,'Paul')//第一個參數是要插入的位置
print L

這裏寫圖片描述
list中刪除元素:刪除一個元素,使用的是pop()方法,不傳遞參數時,刪除的是最後一位,傳遞參數時爲刪除指定位置的元素,且返回值是 刪除的那個元素的值

L = ['Adam', 'Lisa', 'Paul', 'Bart']
L.pop()
L.pop(0)
print L

這裏寫圖片描述
list中替換元素:直接給對應下標重新賦值即可:L[0]=’abc’
二、tuple
tuple是另一種有序的列表,中文翻譯爲“ 元組 ”。tuple 和 list 非常類似,但是,tuple一旦創建完畢,就不能修改了。創建tuple和創建list唯一不同之處是用( )替代了[ ]。現在,這個 t 就不能改變了,tuple沒有 append()方法,也沒有insert()和pop()方法。不能再添加、刪除和修改元素。訪問元祖中的元素和list是一模一樣的
需要注意的是,當tuple中包含一個元素的時候,我們需要這樣寫t=(1,)(是字符串的時候,也需要加“逗號”),也就是在後邊加一個“逗號”。因爲()既可以表示tuple,又可以作爲括號表示運算時的優先級,結果 (1) 被Python解釋器計算出結果 1,導致我們得到的不是tuple,而是整數 1。正是因爲用()定義單元素的tuple有歧義,所以 Python 規定,單元素 tuple 要多加一個逗號“,”,這樣就避免了歧義

下邊我們看一個“可變”的tuple
t = (‘a’, ‘b’, [‘A’, ‘B’])
注意到 t 有 3 個元素:’a’,’b’和一個list:[‘A’, ‘B’]。list作爲一個整體是tuple的第3個元素。list對象可以通過 t[2] 拿到:L=t[2]
然後,我們把list的兩個元素改一改:
L[0] = ‘X’
L[1] = ‘Y’
再看看tuple的內容:
print t
(‘a’, ‘b’, [‘X’, ‘Y’])
不是說tuple一旦定義後就不可變了嗎?怎麼現在又變了?

別急,我們先看看定義的時候tuple包含的3個元素
這裏寫圖片描述
當我們把list的元素’A’和’B’修改爲’X’和’Y’後,tuple變爲:
這裏寫圖片描述
表面上看,tuple的元素確實變了,但其實變的不是 tuple 的元素,而是list的元素。

tuple一開始指向的list並沒有改成別的list,所以,tuple所謂的“不變”是說,tuple的每個元素,指向永遠不變。即指向’a’,就不能改成指向’b’,指向一個list,就不能改成指向其他對象,但指向的這個list本身是可變的!

理解了“指向不變”後,要創建一個內容也不變的tuple怎麼做?那就必須保證tuple的每一個元素本身也不能變。
三、dict
我們已經知道,list 和 tuple 可以用來表示順序集合。dict是一種包含key,value的集合,它的表示方法爲:

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}

花括號 {} 表示這是一個dict,然後按照 key: value, 寫出來即可。最後一個 key: value 的逗號可以省略。由於dict也是集合,len() 函數可以計算任意集合的大小:len(d),輸出爲3
訪問dict:

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}

可以簡單地使用 d[key] 的形式來查找對應的 value,這和 list 很像,不同之處是,list 必須使用索引返回對應的元素,而dict使用key:print d[‘Adam’] 輸出95

注意: 通過 key 訪問 dict 的value,只要 key 存在,dict就返回對應的value。如果key不存在,會直接報錯:KeyError。
要避免 KeyError 發生,有兩個辦法:
一是先判斷一下 key 是否存在,用 in 操作符:

if 'Paul' in d:
    print d['Paul']

如果 ‘Paul’ 不存在,if語句判斷爲False,自然不會執行 print d[‘Paul’] ,從而避免了錯誤。

二是使用dict本身提供的一個 get 方法,在Key不存在的時候,返回None:

print d.get('Bart')
59
print d.get('Paul')
None

dict特點:
dict的第一個特點是查找速度快,無論dict有10個元素還是10萬個元素,查找速度都一樣。而list的查找速度隨着元素增加而逐漸下降。

不過dict的查找速度快不是沒有代價的,dict的缺點是佔用內存大,還會浪費很多內容,list正好相反,佔用內存小,但是查找速度慢。

由於dict是按 key 查找,所以,在一個dict中,key不能重複。

dict的第二個特點就是存儲的key-value序對是沒有順序的!這和list不一樣:

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}

當我們試圖打印這個dict時打印的順序不一定是我們創建時的順序,而且,不同的機器打印的順序都可能不同,這說明dict內部是無序的,不能用dict存儲有序的集合。

dict的第三個特點是作爲 key 的元素必須不可變,Python的基本類型如字符串、整數、浮點數都是不可變的,都可以作爲 key。但是list是可變的,就不能作爲 key。
更新dict:
dict是可變的,也就是說,我們可以隨時往dict中添加新的 key-value。比如已有dict:

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
d['Paul'] = 72
print(L)
{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 59}

如果 key 已經存在,則賦值會用新的 value 替換掉原來的 value
遍歷dict:

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
for key in d:  
    print key + ':',d[key]

四、set
dict的作用是建立一組 key 和一組 value 的映射關係,dict的key是不能重複的。

有的時候,我們只想要 dict 的 key,不關心 key 對應的 value,目的就是保證這個集合的元素不會重複,這時,set就派上用場了。

set 持有一系列元素,這一點和 list 很像,但是set的元素沒有重複,而且是無序的,這點和 dict 的 key很像。

創建 set 的方式是調用 set() 並傳入一個 list,list的元素將作爲set的元素:

s = set(['A', 'B', 'C'])

可以查看 set 的內容:
print s
set([‘A’, ‘C’, ‘B’])
請注意,上述打印的形式類似 list, 但它不是 list,仔細看還可以發現,打印的順序和原始 list 的順序有可能是不同的,因爲set內部存儲的元素是無序的。

因爲set不能包含重複的元素,所以,當我們傳入包含重複元素的 list 會怎麼樣呢?

s = set(['A', 'B', 'C', 'C'])
print s
set(['A', 'C', 'B'])
len(s)
3

結果顯示,set會自動去掉重複的元素,原來的list有4個元素,但set只有3個元素。
訪問set:
由於set存儲的是無序集合,所以我們沒法通過索引來訪問。訪問 set中的某個元素實際上就是判斷一個元素是否在set中。
例如,存儲了班裏同學名字的set:

s = set(['Adam', 'Lisa', 'Bart', 'Paul'])

我們可以用 in 操作符判斷:(在就返回true,不在返回false)
Bart是該班的同學嗎?
‘Bart’ in s
True
set的特點:
set的內部結構和dict很像,唯一區別是不存儲value,因此,判斷一個元素是否在set中速度很快。set存儲的元素和dict的key類似,必須是不變對象,因此,任何可變對象是不能放入set中的。最後,set存儲的元素也是沒有順序的。set的這些特點,可以應用在哪些地方呢?

星期一到星期日可以用字符串’MON’, ‘TUE’, … ‘SUN’表示。

假設我們讓用戶輸入星期一至星期日的某天,如何判斷用戶的輸入是否是一個有效的星期呢?

可以用 if 語句判斷,但這樣做非常繁瑣
如果事先創建好一個set,包含’MON’ ~ ‘SUN’:

weekdays = set([‘MON’, ‘TUE’, ‘WED’, ‘THU’, ‘FRI’, ‘SAT’, ‘SUN’])
再判斷輸入是否有效,只需要判斷該字符串是否在set中:

x = '???' # 用戶輸入的字符串
if x in weekdays:
    print 'input ok'
else:
    print 'input error'

這樣一來,代碼就簡單多了。
遍歷set:
由於 set 也是一個集合,所以,遍歷 set 和遍歷 list 類似,都可以通過 for 循環實現。
直接使用 for 循環可以遍歷 set 的元素:

s = set(['Adam', 'Lisa', 'Bart'])
for name in s:
...     print name
... 
Lisa
Adam
Bart

注意: 觀察 for 循環在遍歷set時,元素的順序和list的順序很可能是不同的,而且不同的機器上運行的結果也可能不同。
更新set:
由於set存儲的是一組不重複的無序元素,因此,更新set主要做兩件事:一是把新的元素添加到set中,二是把已有元素從set中刪除。添加元素時,用set的add()方法:

s = set([1, 2, 3])
s.add(4)
print s
set([1, 2, 3, 4])

如果添加的元素已經存在於set中,add()不會報錯,但是不會加進去了:

s = set([1, 2, 3])
s.add(3)
print s
set([1, 2, 3])

刪除set中的元素時,用set的remove()方法:

s = set([1, 2, 3, 4])
s.remove(4)
print s
set([1, 2, 3])

如果刪除的元素不存在set中,remove()會報錯:

s = set([1, 2, 3])
s.remove(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 4

所以用add()可以直接添加,而remove()前需要判斷。
五、切片
(1)對list進行切片
取一個list的部分元素是非常常見的操作。比如,一個list如下:

L = ['Adam', 'Lisa', 'Bart', 'Paul']

取前3個元素,應該怎麼做?
笨辦法:

[L[0], L[1], L[2]]
['Adam', 'Lisa', 'Bart']

之所以是笨辦法是因爲擴展一下,取前N個元素就沒轍了。取前N個元素,也就是索引爲0-(N-1)的元素,可以用循環:

r = []
n = 3
for i in range(n):
...     r.append(L[i])
... 
print r
['Adam', 'Lisa', 'Bart']

對這種經常取指定索引範圍的操作,用循環十分繁瑣,因此,Python提供了切片(Slice)操作符,能大大簡化這種操作。

對應上面的問題,取前3個元素,用一行代碼就可以完成切片:
L[0:3]
[‘Adam’, ‘Lisa’, ‘Bart’]
L[0:3]表示,從索引0開始取,直到索引3爲止,但不包括索引3。即索引0,1,2,正好是3個元素。
如果第一個索引是0,還可以省略:
L[:3]
[‘Adam’, ‘Lisa’, ‘Bart’]
也可以從索引1開始,取出2個元素出來:
L[1:3]
[‘Lisa’, ‘Bart’]
只用一個 : ,表示從頭到尾:
L[:]
[‘Adam’, ‘Lisa’, ‘Bart’, ‘Paul’]
因此,L[:]實際上覆製出了一個新list。
切片操作還可以指定第三個參數:
L[::2]
[‘Adam’, ‘Bart’]
第三個參數表示每N個取一個,上面的 L[::2] 會每兩個元素取出一個來,也就是隔一個取一個。
把list換成tuple,切片操作完全相同,只是切片的結果也變成了tuple。
(2)倒序切片
對於list,既然Python支持L[-1]取倒數第一個元素,那麼它同樣支持倒數切片,試試:

L = ['Adam', 'Lisa', 'Bart', 'Paul']
L[-2:]
輸出:['Bart', 'Paul']
L[:-2]
輸出:['Adam', 'Lisa']
L[-3:-1]
輸出:['Lisa', 'Bart']
L[-4:-1:2]
輸出:['Adam', 'Bart']

記住倒數第一個元素的索引是-1。倒序切片包含起始索引,不包含結束索引。
(3)對字符串切片
字符串 ‘xxx’和 Unicode字符串 u’xxx’也可以看成是一種list,每個元素就是一個字符。因此,字符串也可以用切片操作,只是操作結果仍是字符串:

'ABCDEFG'[:3]
輸出:'ABC'
'ABCDEFG'[-3:]
輸出:'EFG'
'ABCDEFG'[::2]
輸出:'ACEG'

在很多編程語言中,針對字符串提供了很多各種截取函數,其實目的就是對字符串切片。Python沒有針對字符串的截取函數,只需要切片一個操作就可以完成,非常簡單。
六、迭代
(1)什麼是迭代
在Python中,如果給定一個list或tuple,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們成爲迭代(Iteration)。

在Python中,迭代是通過 for … in 來完成的,而很多語言比如C或者Java,迭代list是通過下標完成的,比如Java代碼:

for (i=0; i<list.length; i++) {
    n = list[i];
}

可以看出,Python的for循環抽象程度要高於Java的for循環。
因爲 Python 的 for循環不僅可以用在list或tuple上,還可以作用在其他任何可迭代對象上。
因此,迭代操作就是對於一個集合,無論該集合是有序還是無序,我們用 for 循環總是可以依次取出集合的每一個元素。
注意: 集合是指包含一組元素的數據結構,我們已經介紹的包括:
**1. 有序集合:**list,tuple,str和unicode;
**2. 無序集合:**set
**3. 無序集合並且具有 key-value 對:**dict
而迭代是一個動詞,它指的是一種操作,在Python中,就是 for 循環。

迭代與按下標訪問數組最大的不同是,後者是一種具體的迭代實現方式,而前者只關心迭代結果,根本不關心迭代內部是如何實現的。
(2)索引迭代
Python中,迭代永遠是取出元素本身,而非元素的索引。

對於有序集合,元素確實是有索引的。有的時候,我們確實想在 for 循環中拿到索引,怎麼辦?

方法是使用 enumerate() 函數:

L = ['Adam', 'Lisa', 'Bart', 'Paul']
for index, name in enumerate(L):
...     print index, '-', name
輸出: 
0 - Adam
1 - Lisa
2 - Bart
3 - Paul

使用 enumerate() 函數,我們可以在for循環中同時綁定索引index和元素name。但是,這不是 enumerate() 的特殊語法。實際上,enumerate() 函數把:

[‘Adam’, ‘Lisa’, ‘Bart’, ‘Paul’]
變成了類似:
[(0, ‘Adam’), (1, ‘Lisa’), (2, ‘Bart’), (3, ‘Paul’)]
因此,迭代的每一個元素實際上是一個tuple:

for t in enumerate(L):
    index = t[0]
    name = t[1]
    print index, '-', name

如果我們知道每個tuple元素都包含兩個元素,for循環又可以進一步簡寫爲:
for index, name in enumerate(L):
print index, ‘-‘, name
這樣不但代碼更簡單,而且還少了兩條賦值語句。

可見,索引迭代也不是真的按索引訪問,而是由 enumerate() 函數自動把每個元素變成 (index, element) 這樣的tuple,再迭代,就同時獲得了索引和元素本身。
(3)迭代dict的value
我們已經瞭解了dict對象本身就是可迭代對象,用 for 循環直接迭代 dict,可以每次拿到dict的一個key。

如果我們希望迭代 dict 對象的value,應該怎麼做?

dict 對象有一個 values() 方法,這個方法把dict轉換成一個包含所有value的list,這樣,我們迭代的就是 dict的每一個 value:

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
[85,59,95]
for v in d.values():
    print v
85
59
95

如果仔細閱讀Python的文檔,還可以發現,dict除了values()方法外,還有一個 itervalues() 方法,用 itervalues() 方法替代 values() 方法,迭代效果完全一樣:

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.itervalues()
<dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues():
    print v
85
95
59

那這兩個方法有何不同之處呢?
1. values() 方法實際上把一個 dict 轉換成了包含 value 的list。
2. 但是 itervalues() 方法不會轉換,它會在迭代過程中依次從 dict 中取出 value,所以 itervalues() 方法比 values() 方法節省了生成 list 所需的內存。

  1. 打印 itervalues() 發現它返回一個 對象,這說明在Python中,for 循環可作用的迭代對象遠不止 list,tuple,str,unicode,dict等,任何可迭代對象都可以作用於for循環,而內部如何迭代我們通常並不用關心。

如果一個對象說自己可迭代,那我們就直接用 for 循環去迭代它,可見,迭代是一種抽象的數據操作,它不對迭代對象內部的數據有任何要求。
(4)迭代dict的key和value
我們瞭解瞭如何迭代 dict 的key和value,那麼,在一個 for 循環中,能否同時迭代 key和value?答案是肯定的。

首先,我們看看 dict 對象的 items() 方法返回的值:

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.items()
輸出:[('Lisa', 85), ('Adam', 95), ('Bart', 59)]

可以看到,items() 方法把dict對象轉換成了包含tuple的list,我們對這個list進行迭代,可以同時獲得key和value:

for key, value in d.items():
...     print key, ':', value
輸出:
Lisa : 85
Adam : 95
Bart : 59

和 values() 有一個 itervalues() 類似, items() 也有一個對應的 iteritems(),iteritems() 不把dict轉換成list,而是在迭代過程中不斷給出 tuple,所以, iteritems() 不佔用額外的內存。
七、列表生成式
(1)生成列表
要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我們可以用range(1, 11):
range(1, 11)
輸出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
但如果要生成[1x1, 2x2, 3x3, …, 10x10]怎麼做?方法一是循環:

L = []
for x in range(1, 11):
...    L.append(x * x)
... 
>>> L
輸出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

但是循環太繁瑣,而列表生成式則可以用一行語句代替循環生成上面的list:
[x * x for x in range(1, 11)]
輸出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
這種寫法就是Python特有的列表生成式。利用列表生成式,可以以非常簡潔的代碼生成 list。

寫列表生成式時,把要生成的元素 x * x 放到前面,後面跟 for 循環,就可以把list創建出來,十分有用,多寫幾次,很快就可以熟悉這種語法。
(2)條件過濾
列表生成式的 for 循環後面還可以加上 if 判斷。例如:

[x * x for x in range(1, 11)]
輸出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
如果我們只想要偶數的平方,不改動 range()的情況下,可以加上 if 來篩選:

[x * x for x in range(1, 11) if x % 2 == 0]
輸出:[4, 16, 36, 64, 100]
有了 if 條件,只有 if 判斷爲 True 的時候,才把循環的當前元素添加到列表中。
(3)多層表達式
for循環可以嵌套,因此,在列表生成式中,也可以用多層 for 循環來生成列表。

對於字符串 ‘ABC’ 和 ‘123’,可以使用兩層循環,生成全排列:

[m + n for m in 'ABC' for n in '123']
輸出:['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

翻譯成循環代碼就像下面這樣:

L = []
for m in 'ABC':
    for n in '123':
        L.append(m + n)

初學python,希望這些能夠對大家有所幫助^_^,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章