Python入門序列(列表,元組,字典,集合)

序列

序列是一種數據存儲方式,用來存儲一系列的數據。在內存中,序列就是一塊用來存放多個值的連續的內存空間。比如一個整數序列[10,20,30,40],可以這樣示意表示:


由於 Python3 中一切皆對象,在內存中實際是按照如下方式存儲的:
a = [10,20,30,40]


從圖示中,我們可以看出序列中存儲的是整數對象的地址,而不是整數對象的值。python
中常用的序列結構有:字符串、列表、元組、字典、集合

列表簡介
列表:用於存儲任意數目、任意類型的數據集合。
列表是內置可變序列,是包含多個元素的有序連續的內存空間。列表定義的標準語法格式:
a = [10,20,30,40]其中,10,20,30,40 這些稱爲:列表 a 的元素。
列表中的元素可以各不相同,可以是任意類型。比如:a = [10,20,'abc',True]

Python 的列表大小可變,根據需要隨時增加或縮小。
字符串和列表都是序列類型,一個字符串是一個字符序列,一個列表是任何元素的序列

基本語法[]創建

list()創建 range()創建
使用 list()可以將任何可迭代的數據轉化成列表。range()可以幫助我們非常方便的創建整數列表,語法格式爲:
range([start,] end [,step])

append()方法

原地修改列表對象,是真正的列表尾部添加新的元素,速度最快,推薦使用。

 

+運算符操作
並不是真正的尾部添加元素, 而是創建新的列表對象; 將原列表的元素和新列表的元素依次
複製到新的列表對象中。這樣,會涉及大量的複製操作,對於操作大量元素不建議使用。

通過如上測試,我們發現變量 a 的地址發生了變化。也就是創建了新的列表對象。

extend()方法
將目標列表的所有元素添加到本列表的尾部,屬於原地操作,不創建新的列表對象。

insert()插入元素
使用 insert()方法可以將指定的元素插入到列表對象的任意制定位置。這樣會讓插入位置後面所有的元素進行移動,會影響處理速度。涉及大量元素時,儘量避免使用。類似發生這種移動的函數還有:remove()、pop()、del(),它們在刪除非尾部元素時也會發生操作位置後面元素的移動。

del 刪除
刪除列表指定位置的元素。

pop()方法
pop()刪除並返回指定位置元素,如果未指定位置則默認操作列表最後一個元素。

remove()方法
刪除首次出現的指定元素,若不存在該元素拋出異常。

通過索引直接訪問元素
可以通過索引直接訪問元素。 索引的區間在[0, 列表長度-1]這個範圍。 超過這個範圍則會拋出異常。

index()獲得指定元素在列表中首次出現的索引
index()可以獲取指定元素首次出現的索引位置。 語法是: index(value,[start,[end]])。 其中,start 和 end 指定了搜索的範圍。

count()獲得指定元素在列表中出現的次數
count()可以返回指定元素在列表中出現的次數。

成員資格判斷
判斷列表中是否存在指定的元素,我們可以使用 count()方法,返回 0 則表示不存在,返回大於 0 則表示存在。但是,一般我們會使用更加簡潔的 in 關鍵字來判斷,直接返回 True或 False。

切片操作
在前面字符串章節,提到過字符串的切片操作,對於列表的切片操作和字符串類似。
切片是 Python 序列及其重要的操作,適用於列表、元組、字符串等等。切片的格式如下:
切片 slice 操作可以讓我們快速提取子列表或修改。標準格式爲:[起始偏移量 start:終止偏移量 end[:步長 step]]
注:當步長省略時順便可以省略第二個冒號

切片操作時,起始偏移量和終止偏移量不在[0,字符串長度-1]這個範圍,也不會報錯。起始偏移量小於 0 則會當做 0,終止偏移量大於“長度-1”會被當成”長度-1”

列表排序
修改原列表,不建新列表的排序

建新列表的排序
我們也可以通過內置函數 sorted()進行排序,這個方法返回新列表,不對原列表做修改。

reversed()返回迭代器
內置函數 reversed()也支持進行逆序排列,與列表對象 reverse()方法不同的是,內置函數
reversed()不對原列表做任何修改,只是返回一個逆序排列的迭代器對象。

打印輸出 b 發現提示是:list_reverseiterator。也就是一個迭代對象。同時,我們使用list(b)進行輸出,發現只能使用一次。第一次輸出了元素,第二次爲空。那是因爲迭代對象在第一次時已經遍歷結束了,第二次不能再使用。(類似遊標指針)

列表相關的其他內置函數彙總

 

 

 

元組 tuple
列表屬於可變序列,可以任意修改列表中的元素。元組屬於不可變序列,不能修改元組中的
元素。因此,元組沒有增加元素、修改元素、刪除元素相關的方法。

元組的創建
通過()創建元組。小括號可以省略。
a = (10,20,30)或者a = 10,20,30
如果元組只有一個元素, 則必須後面加逗號。 這是因爲解釋器會把(1)解釋爲整數 1, (1,)解釋爲元組。

 通過 tuple()創建元組 tuple(可迭代的對象)

總結:
tuple()可以接收列表、字符串、其他序列類型、迭代器等生成元組。
list()可以接收元組、字符串、其他序列類型、迭代器等生成列表。

元組的元素訪問和計數
1. 元組的元素不能修改

列表關於排序的方法 list.sorted()是修改原列表對象,元組沒有該方法。如果要對元組排
序,只能使用內置函數 sorted(tupleObj)

zip
zip(列表 1,列表 2,...)將多個列表對應位置的元素組合成爲元組,並返回這個 zip 對象。

元組總結
1. 元組的核心特點是:不可變序列。
2. 元組的訪問和處理速度比列表快。
3. 與整數和字符串一樣,元組可以作爲字典的鍵,列表則永遠不能作爲字典的鍵使用。

 

 

字典介紹
字典是“鍵值對”的無序可變序列,字典中的每個元素都是一個“鍵值對”,包含: “鍵對象”和“值對象”。可以通過“鍵對象”實現快速獲取、刪除、更新對應的“值對象”。列表中我們通過“下標數字”找到對應的對象。字典中通過“鍵對象”找到對應的“值對象”。“鍵”是任意的不可變數據,比如:整數、浮點數、字符串、元組。但是:列表、字典、集合這些可變對象,不能作爲“鍵”。並且“鍵”不可重複。“值”可以是任意的數據,並且可重複。一個典型的字典的定義方式:a = {'name':'gaoqi','age':18,'job':'programmer'}
字典的創建
1. 我們可以通過{}、dict()來創建字典對象。

2. 通過 zip()創建字典對象

3. 通過 fromkeys 創建值爲空的字典

字典元素的訪問

 1.通過[鍵]獲得“值”。若鍵不存在,則拋出異常。

2. 通過 get()方法獲得“值”。推薦使用。優點是:指定鍵不存在,返回 None;也可以設
定指定鍵不存在時默認返回的對象。推薦使用 get()獲取“值對象”。

 3.列出所有的鍵值對

字典元素添加、修改、刪除

1. 給字典新增“鍵值對”。如果“鍵”已經存在,則覆蓋舊的鍵值對;如果“鍵”不存在,則新增“鍵值對”

2. 使用 update()將新字典中所有鍵值對全部添加到舊字典對象上。如果 key 有重複,則直接覆蓋。

3. 字典中元素的刪除,可以使用 del()方法;或者 clear()刪除所有鍵值對;pop()刪除指定鍵值對,並返回對應的“值對象”

4.popitem() :隨機刪除和返回該鍵值對。字典是“無序可變序列”,因此沒有第一個元素、最後一個元素的概念;popitem 彈出隨機的項,因爲字典並沒有"最後的元素"或者其他有關順序的概念。若想一個接一個地移除並處理項,這個方法就非常有效(因爲不用首先獲取鍵的列表)。

序列解包
序列解包可以用於元組、列表、字典。序列解包可以讓我們方便的對多個變量賦值.序列解包用於字典時,默認是對“鍵”進行操作; 如果需要對鍵值對操作,則需要使用items();如果需要對“值”進行操作,則需要使用 values()

 

字典核心底層原理(重要)
字典對象的核心是散列表。散列表是一個稀疏數組(總是有空白元素的數組),數組的每個單元叫做 bucket。每個 bucket 有兩部分:一個是鍵對象的引用,一個是值對象的引用。由於所有 bucket 結構和大小一致,我們可以通過偏移量來讀取指bucket。

將一個鍵值對放進字典的底層過程

假設字典 a 對象創建完後,數組長度爲 7:

我要把”name”=”gaochenxi”這個鍵值對放到字典對象 a 中,第一步需要計算鍵”name”的散列值。Python 中通過 hash()來計算。

由於數組長度爲 7,我們可以拿計算出的散列值的最右邊 3 位數字作爲偏移量,即“000”,十進制是數字 0。我們查看偏移量 0,對應的 bucket 是否爲空。如果爲空,則將鍵值對放進去。如果不爲空,則依次取右邊 3 位作爲偏移量,即“010”,十進制是數字
2。再查看偏移量爲 2 的 bucket 是否爲空。直到找到爲空的 bucket 將鍵值對放進去。流程圖如下:

擴容
python 會根據散列表的擁擠程度擴容。“擴容”指的是:創造更大的數組,將原內容拷貝到新數組中。接近 2/3 時,數組就會擴容。

根據鍵查找“鍵值對”的底層過程

當我們調用 a.get(“name”),就是根據鍵“name”查找到“鍵值對”,從而找到值對象“gaochenxi”。
第一步,我們仍然要計算“name”對象的散列值:

和存儲的底層流程算法一致,也是依次取散列值的不同位置的數字。 假設數組長度爲7,我們可以拿計算出的散列值的最右邊 3 位數字作爲偏移量,即“00”,十進制是數字0。我們查看偏移量 0,對應的 bucket 是否爲空。如果爲空,則返回 None。如果不爲空,則將這個 bucket 的鍵對象計算對應散列值,和我們的散列值進行比較,如果相等。則將對應“值對象”返回。如果不相等,則再依次取其他幾位數字,重新計算偏移量。依次取完後,仍然沒有找到。則返回 None。流程圖如下:

用法總結:
1. 鍵必須可散列
    (1) 數字、字符串、元組,都是可散列的。
    (2) 自定義對象需要支持下面三點:
         1支持 hash()函數
         2支持通過__eq__()方法檢測相等性。
         3若 a==b 爲真,則 hash(a)==hash(b)也爲真。
2. 字典在內存中開銷巨大,典型的空間換時間。
3. 鍵查詢速度很快
4. 往字典裏面添加新建可能導致擴容,導致散列表中鍵的次序變化。因此,不要在遍歷字典的同時進行字典的修改。

 

 

集合
集合是無序可變元素不能重複。實際上集合底層是字典實現,集合的所有元素都是字典中的“鍵對象”,因此是不能重複的且唯一

集合創建和刪除

1. 使用{}創建集合對象,並使用 add()方法添加元素

2. 使用 set(),將列表、元組等可迭代對象轉成集合。如果原來數據存在重複數據,則只保留一個。

3. remove()刪除指定元素;clear()清空整個集合

集合相關操作,像數學中概念一樣,Python 對集合也提供了並集、交集、差集等運算。給出示例:

推導式創建序列
推導式是從一個或者多個迭代器快速創建序列的一種方法。它可以將循環和條件判斷結合,從而避免冗長的代碼。推導式是典型的 Python 風格


列表推導式
列表推導式生成列表對象,語法如下:
       [表達式foritemin 可迭代對象 ]或者:{表達式foritemin 可迭代對象if條件判斷}
>>> [x for x in range(1,5)]
[1, 2, 3, 4]
>>> [x*2 for x in range(1,5)]
[2, 4, 6, 8]
>>> [x*2 for x in range(1,20) if x%5==0 ]
[10, 20, 30]
>>> [aforain "abcdefg"]
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> cells = [(row,col) forrow in range(1,10) for col in range(1,10)]#可以使用兩個循環
>>> for cell in cells:
print(cell)


字典推導式
字典的推導式生成字典對象,格式如下:
{key_expression:value_expressionfor表達式in可迭代對象}類似於列表推導式,字典推導也可以增加 if 條件判斷、多個 for 循環。
統計文本中字符出現的次數:
>>> my_text = ' i love you, i love china, i love gao'
>>> char_count = {c:my_text.count(c)for c in my_text}
>>> char_count
{' ': 9, 'i': 4, 'l': 3, 'o': 5, 'v': 3, 'e': 3, 'y': 1, 'u': 1, ',': 2, 'h': 1, 'n': 1, 'c': 1, 'g': 1, 'a': 2}


集合推導式
集合推導式生成集合,和列表推導式的語法格式類似:
{表達式foritemin 可迭代對象 }或者:{表達式foritemin 可迭代對象if條件判斷}
>>> {x for x in range(1,100) if x%9==0}
{99, 36, 72, 9, 45, 81, 18, 54, 90, 27, 63}


生成器推導式(生成元組)
>>> (x for x in range(1,100) if x%9==0)
<generator object <genexpr> at 0x0000000002BD3048>
我們發現提示的是“一個生成器對象”。顯然,元組是沒有推導式的。一個生成器只能運行一次。第一次迭代可以得到數據,第二次迭代發現數據已經沒有了。
>>> gnt = (x for x in range(1,100) if x%9==0)
>>> for x in gnt:
print(x,end=' ')
9 18 27 36 45 54 63 72 81 90 99
>>> for x in gnt:
print(x,end=' ')
>>>

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