官术网_书友最值得收藏!

第5章 列表、元組和字符串

5.1 列表:一個“打了激素”的數組

視頻講解

有時候可能需要將一些相互之間有關聯的數據保存到一起,很多接觸過編程的讀者腦海里浮現出來的第一個概念應該就是數組。數組允許把一些相同類型的數據挨個兒擺在一起,然后通過下標進行索引。

Python也有類似數組的東西,不過更為強大。由于Python的變量沒有數據類型,所以Python的“數組”可以同時存放不同類型的變量。這么厲害的東西,Python將其稱為列表,姑且可以認為列表就是一個“打了激素”的數組。

5.1.1 創建列表

創建一個列表非常簡單,只需要使用中括號將數據包裹起來(數據之間用逗號分隔)就可以了。

     >>> [1, 2, 3, 4, 5]
     [1, 2, 3, 4, 5]

上面創建了一個匿名的列表,因為沒有名字,所以創建完也沒辦法再次使用它。為了可以隨時對它進行引用和修改,可以給它貼上一個變量名:

注意:

type()函數用于返回指定參數的類型,list即列表的意思。

沒有哪一項規定要求Python的列表保存同一類型的數據,因此,它支持將各種不同的數據存放到一起:

     >>> mix = [520, "小甲魚", 3.14, [1, 2, 3]]

可以看到這個列表里有整型、字符串、浮點型數據,甚至還可以包含另一個列表。

當實在想不到要往列表里面塞什么數據的時候,可以先創建一個空列表:

     >>> empty = []

5.1.2 向列表添加元素

列表并不是一成不變的,可以隨意地往里面添加新的元素。添加元素到列表中,可以使用append()方法:

     >>> number = [1, 2, 3, 4, 5]
     >>> number.append(6)
     >>> number
     [1, 2, 3, 4, 5, 6]

可以看到,數字6已經被添加到列表number的末尾了。有讀者可能會問,這個append()的調用怎么跟平時的BIF內置函數調用不一樣呢?

因為append()并不是一個BIF,它是屬于列表對象的一個方法。中間這個“.”,暫時可以理解為范圍的意思:append()這個方法是屬于一個叫number的列表對象的。關于對象的知識,暫時只需要理解這么多,后面小甲魚會再詳細地來介紹對象。

下面代碼試圖將數字8和9同時添加進number列表中:

出錯了,這是因為append()方法只支持一個參數。

如果希望同時添加多個數據,可以使用extend()方法向列表末尾添加多個元素:

     >>> number.extend([8, 9])
     >>> number
     [1, 2, 3, 4, 5, 6, 8, 9]

注意:

extend()事實上是使用一個列表來擴充另一個列表,所以它的參數是另一個列表。

無論是append()還是extend()方法,都是往列表的末尾添加數據,那么是否可以將數據插入到指定的位置呢?

當然沒問題,想要往列表的任意位置插入元素,可以使用到insert()方法。

insert()方法有兩個參數:第一個參數指定待插入的位置(索引值),第二個參數是待插入的元素值。

下面代碼將數字0插入到number列表的最前面:

     >>> number.insert(0, 0)
     >>> number
     [0, 1, 2, 3, 4, 5, 6, 8, 9]

在計算機編程中常常會出現一些“反常識”的知識點,如在Python列表中,第一個位置的索引值是0,第二個是1,第三個是2,以此類推……

下面代碼將數字7插入到6和8之間:

     >>> number.insert(7, 7)
     >>> number
     [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

insert()方法中代表位置的第一個參數還支持負數,表示與列表末尾的相對距離:

     >>> number.insert(-1, 8.5)
     >>> number
     [0, 1, 2, 3, 4, 5, 6, 7, 8, 8.5, 9]

5.1.3 從列表中獲取元素

視頻講解

通過索引值可以直接獲取列表中的某個元素:

     >>> eggs = ["雞蛋", "鴨蛋", "鵝蛋", "鐵蛋"]
     >>> eggs[0]
     '雞蛋'
     >>> eggs[3]
     '鐵蛋'

如果想要訪問列表中最后一個元素,怎么辦?可以使用len()函數獲取該列表的長度(元素個數),再減1就是這個列表最后一個元素的索引值:

     >>> eggs = ["雞蛋", "鴨蛋", "鵝蛋", "鐵蛋"]
     >>> eggs[len(eggs)-1]
     '鐵蛋'
     >>> eggs[len(eggs)-2]
     '鵝蛋'

len()函數的調用直接省去也可以實現同樣的效果,即當索引值為負數時,表示從列表的末尾反向索引:

如果要將“鴨蛋”和“鐵蛋”的位置進行調換,通常可以這么寫:

這里的temp是一個臨時變量,避免相互覆蓋。不過Python允許適當地“偷懶”,下面代碼可以實現相同的功能:

有時候可能需要開發一個具有“抽獎”功能的程序,只需要先將“獎項/參與者”放到列表里面,然后配合random模塊即可實現:

random的choice()方法可以從一個非空的序列(如列表)中隨機獲取一個元素。

列表中還可以包含另一個列表,如果要獲取內部子列表的某個元素,應該使用兩次索引:

5.1.4 從列表刪除元素

從列表中刪除元素,可以有三種方法實現:remove()、pop()和del。

remove()方法需要指定一個待刪除的元素:

使用remove()刪除元素,并不需要知道這個元素在列表中的具體位置。但是如果指定的元素不存在于列表中,程序就會報錯:

pop()方法是將列表中的指定元素“彈”出來,也就是取出并刪除該元素的意思,它的參數是一個索引值:

如果不帶參數,pop()方法默認是彈出列表中的最后一個元素:

最后一個是del語句,注意,它是一個Python語句,而不是del列表的方法,或者BIF:

del語句在Python中的用法非常豐富,不僅可以用來刪除列表中的某個(些)元素,還可以直接刪除整個變量:

分析:上面代碼由于eggs整個變量被del語句刪除了,所以再次引用時,Python由于找不到該變量,便會報錯。

5.1.5 列表切片

切片(slice)語法的引入,使得Python的列表真正地走向了高端。這個連Python之父都愛不釋手的語法真有那么神奇嗎?不妨來試一試。

現在要求將列表list1中的三個元素取出來,放到列表list2里面。學了前面的知識,可以使用“笨”方法來實現:

像這樣,從一個列表中取出部分元素是非常常見的操作,但這里是取出三個元素,如果要求取出列表中最后200個元素,那不是很心酸?

其實動動腦筋還是可以實現的:

雖然可以實現,但是每次都要套個循環跑一圈,未免也太煩瑣了!切片的引入,大大地簡化了這種操作:

很簡單對吧?只不過是用一個冒號隔開兩個索引值,左邊是開始位置,右邊是結束位置。這里要注意的一點是:結束位置上的元素是不包含的(如上面例子中,“神奇女俠”的索引值是4,如果寫成list1[2:4],便不能將其包含進來)。

使用列表切片也可以“偷懶”,之前提到過Python是以簡潔而聞名于世,所以你能想到的“便捷方案”,Python的作者以及Python社區的小伙伴們都已經想到了,并付諸實踐,你要做的就是驗證一下是否可行:

如果省略了開始位置,Python會從0這個位置開始。同樣道理,如果要得到從指定索引值到列表末尾的所有元素,把結束位置也省去即可。如果啥都沒有,只有一個冒號,Python將返回整個列表的拷貝。

這種方法有時候非常方便,如想獲取列表最后的幾個元素,可以這么寫:

注意:

列表切片并不會修改列表自身的組成結構和數據,它其實是為列表創建一個新的拷貝(副本)并返回。

5.1.6 進階玩法

列表切片操作實際上還可以接受第三個參數,其代表的是步長,默認值為1。下面將步長修改為2,看看有什么神奇的效果?

其實該代碼還可以直接寫成list1[::2],實現效果是一樣的。

如果將步長設置為負數,如-1,結果會是怎樣呢?

     >>> list1[::-1]
     [9, 8, 7, 6, 5, 4, 3, 2, 1]

這就很有意思了,將步長設置為-1,相當于將整個列表翻轉過來。

上面這些列表切片操作都是獲取列表加工后(切片)的拷貝,并不會影響到原有列表的結構:

但如果將del語句作用于列表切片,其結果又讓人大跌眼鏡:

     >>> del list1[::2]
     >>> list1
     [2, 4, 6, 8]

是的,del直接作用于原始列表了,因為不這樣做的話,代碼就失去意義了,不是嗎?同樣會作用于原始列表的操作還有為切片后的列表賦值:

     >>> list1 = ["鋼鐵俠", "蜘蛛俠", "蝙蝠俠", "綠燈俠", "神奇女俠"]
     >>> list1[0:2] = ["超人", "閃電俠"]

     >>> list1
     ['超人', '閃電俠', '蝙蝠俠', '綠燈俠', '神奇女俠']

5.1.7 一些常用操作符

視頻講解

此前學過的大多數操作符都可以運用到列表上:

     >>> list1 = [123]
     >>> list2 = [234]
     >>> list1 > list2
     False
     >>> list1 <= list2
     True
     >>> list3 = ['apple']
     >>> list4 = ['pineapple']
     >>> list3 < list4
     True

列表好像挺聰明的,不僅懂得比大小,還知道菠蘿(pineapple)比蘋果(apple)大?那如果列表中不止一個元素呢?結果又會如何?

     >>> list1 = [123, 456]
     >>> list2 = [234, 123]
     >>> list1 > list2
     False

怎么會這樣?Python做出這樣的判斷是基于什么根據呢?總不會是隨機瞎猜的吧?

list1列表兩個元素的和是579,按理應該比list2列表的和357要大,那為什么list1>list2還會返回False呢?

其實,Python的列表原來并沒有我們想象中那么“智能”,當列表包含多個元素的時候,默認是從第一個元素開始比較,只要有一個PK贏了,就算整個列表贏了。字符串比較也是同樣的道理(字符串比較的是每一個字符對應的ASCII碼值的大小)。

前面演示過字符串可以使用加號(+)進行拼接,使用乘號(*)來實現自我復制。這兩個操作符也可以作用于列表:

     >>> list1 = [123, 456]
     >>> list2 = [234, 123]
     >>> list3 = list1 + list2
     >>> list3
     [123, 456, 234, 123]

加號(+)也叫連接操作符,它允許把多個列表對象合并在一起,其實就相當于extend()方法實現的效果。一般情況下建議使用extend()方法來擴展列表,因為這樣顯得更為規范和專業。另外,連接操作符并不能實現列表添加新元素的操作:

乘號(*)也叫重復操作符,重復操作符同樣可以用于列表中:

     >>> list1 = ["FishC"]
     >>> list1 * 3
     ['FishC', 'FishC', 'FishC']

另外有個成員關系操作符大家也不陌生了,我們是在談for循環的時候認識它的,成員關系操作符就是in和not in:

     >>> list1 = ["小豬", "小貓", "小狗", "小甲魚"]
     >>> "小甲魚" in list1
     True
     >>> "小烏龜" not in list1
     True

之前說過列表里邊可以包含另一個列表,那么對于列表中的列表的元素,能不能使用in和not in測試呢?試試便知:

     >>> list1 = ["小豬", "小貓", ["小甲魚", "小烏龜"], "小狗"]
     >>> "小甲魚" in list1
     False
     >>> "小烏龜" not in list1
     True

可見in和not in只能判斷一個層次的成員關系,這跟break和continue語句只能跳出一個層次的循環是一個道理。

在開發中,有時候需要去除列表中重復的數據,只要利用好in和not in,就可以巧妙地實現:

分析:代碼先迭代遍歷old_list的每一個元素,如果該元素不存在于new_list中,便調用列表的append()方法添加進去。

5.1.8 列表的小伙伴們

接下來認識一下列表的小伙伴們,列表有多少小伙伴呢?不妨讓Python自己告訴我們:

產生了一個熟悉又陌生的列表,很多熟悉的方法似曾相識,如append()、extend()、insert()、pop()、remove()都是學過的。下面再給大家介紹幾個常用的方法。

count()方法的作用是統計某個元素在列表中出現的次數:

     >>> list1 = [1, 1, 2, 3, 5, 8, 13, 21]
     >>> list1.count(1)
     2

index()方法的作用是返回某個元素在列表中第一次出現的索引值:

     >>> list1.index(1)
     0

index()方法可以限定查找的范圍:

     >>> start = list1.index(1) + 1
     >>> stop = len(list1)
     >>> list1.index(1, start, stop)
     1

reverse()方法的作用是將整個列表原地翻轉:

     >>> list1 = [1, 1, 2, 3, 5, 8, 13, 21]
     >>> list1.reverse()
     >>> list1
     [21, 13, 8, 5, 3, 2, 1, 1]

sort()方法的作用是對列表元素進行排序:

     >>> list1 = [8, 9, 3, 5, 2, 6, 10, 1, 0]
     >>> list1.sort()
     >>> list1
     [0, 1, 2, 3, 5, 6, 8, 9, 10]

那如果需要從大到小排隊呢?很簡單,先調用sort()方法,列表會先從小到大排好隊,然后調用reverse()方法原地翻轉就可以啦。

什么?太麻煩?好吧,大家真是越來越懶了……很好,“懶”有時候確實是發明創新的原動力。其實,sort()這個方法有三個參數,語法形式為:

     sort(func, key, reverse)

func和key參數用于設置排序的算法和關鍵字,默認是使用歸并排序,算法問題不在這里討論,感興趣的朋友可以參考小甲魚的另一部視頻教程——《數據結構和算法》。這里討論sort()方法的第三個參數:reverse,沒錯,就是剛剛學的那個reverse()方法的reverse。不過這里作為sort()的一個默認參數,它的默認值是sort(reverse=False),表示不顛倒順序。因此,只需要把False改為True,列表就相當于從大到小排序:

     >>> list1 = [8, 9, 3, 5, 2, 6, 10, 1, 0]
     >>> list1.sort(reverse=True)
     >>> list1
     [10, 9, 8, 6, 5, 3, 2, 1, 0]
主站蜘蛛池模板: 福贡县| 屏东县| 澎湖县| 江西省| 收藏| 会同县| 凤阳县| 甘泉县| 宁波市| 西畴县| 共和县| 宿州市| 吴旗县| 林甸县| 铜梁县| 高要市| 钟祥市| 弥渡县| 兖州市| 长治市| 象山县| 翁牛特旗| 平远县| 灵台县| 犍为县| 陈巴尔虎旗| 仪征市| 静海县| 上蔡县| 芦山县| 崇州市| 巴塘县| 调兵山市| 富锦市| 收藏| 永城市| 邹城市| 阿拉善盟| 西林县| 永靖县| 晋中市|