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

3.2 列表

前面已經用了很多次列表,可以看出列表的功能是比較強大的。本節將討論列表不同于元組和字符串的地方:列表的內容是可變的(mutable)。列表有很多比較好用、比較獨特的方法,本節將一一進行介紹。

3.2.1 更新列表

我們在3.1節中所講述的有關序列的操作,如索引、分片、相加、乘法等都適用于列表。本節將介紹一些序列中沒有而列表中有的方法,這些方法的作用都是更新列表,有元素賦值、元素刪除、分片賦值和列表方法。下面逐一進行介紹。

1.元素賦值

我們前面學習過賦值語句,賦值語句是最簡單地改變列表的方式,如a=2就是一種改變列表的方式。這里我們將通過編號標記某個特定位置的元素,并對該位置的元素重新賦值,如a[1]=10。在交互模式輸入如下:

        >>> a=[1,2,3,2,1]
        >>> a[1]=10
        >>> a
        [1, 10, 3, 2, 1]
        >>> a[3]=10
        >>> a
        [1, 10, 3, 10, 1]

還記得我們的編號是從0開始吧!

從上面的輸出結果可以得知,我們可以根據編號對列表中某個元素重新賦值。既然可以重新賦值,是否可以賦不同類型的值呢?我們嘗試一下,輸入如下:

        >>>a[2]='hello'  #對編號為2的元素賦值,賦一個字符串
        >>> a
        [1, 10, 'hello', 10, 1]
        >>> type(a)
        <class 'list'>
        >>>type(a[1])  #別忘了查看類型函數的使用
        <class 'int'>
        >>> type(a[2])
        <class 'str'>

由上面的輸出結果可以得知,可以對一個列表中的元素賦不同類型的值。比如上面的示例,列表a中既有int類型的值,也有str類型的值。

假如對列表賦值時使用的編號超過了列表中的最大編號,是否還可以賦值呢?我們嘗試一下,輸入如下:

        >>> tring=[1,2,3]
        >>> tring[3]='test'
        Traceback (most recent call last):
          File "<pyshell#43>", line 1, in <module>
            tring[3]='test'
        IndexError: list assignment index out of range

在上面的示例中,tring的最大編號是2,當給編號為3的元素賦值時就會出錯。由此得知:不能為一個不存在元素的位置賦值。如果一定要賦值,前面學習的序列通用操作中的乘法可以幫助我們,輸入如下:

        >>> tring=[None]*5
        >>> tring[3]='test'
        >>> tring
        [None, None, None, 'test', None]

由以上輸出結果可以得知,可以對初始化過的位置進行賦值。

注意 不能為一個不存在元素的位置賦值。

2.增加元素

由元素賦值的示例可以看到,不能為一個不存在的位置賦值。一旦初始化了一個列表,就不能再往這個列表中增加元素了。若需要往列表中增加元素,則需要將整個列表中的元素都復制一遍,再添加需要增加的元素。Python中是否提供了對應的方法幫助我們做這件事情呢?答案是肯定的。輸入如下:

        >>> tring=[1,2,3]
        >>> tring.append(4)
        >>> tring
        [1, 2, 3, 4]

由示例看到,可以使用append()方法解決前面的困惑。append()方法是一個用于在列表末尾添加新對象的方法。該方法的語法如下:

list.append(obj)

此語法中list代表列表,obj代表需要添加到list列表末尾的對象。

注意 append的使用方式是list.append(obj)。

由前面的輸出結果得知:append()方法不是簡單地返回一個修改過的新列表,而是直接修改原來的列表。下面展示幾個append()的示例:

        >>> tring=[1,2,3]
        >>>tring.append('test')        #添加字符串
        >>> tring
        [1, 2, 3, 'test']
        >>> s=['a', 'b', 'c']
        >>>s.append(3)             #添加數字
        >>> s
        ['a', 'b', 'c', 3]

由上面的示例可以得知:可以往數字序列中添加字符串,也可以往字符串序列中添加數字。

3.刪除元素

前面學習了往列表中增加元素,是否可以在列表中刪除元素呢?例如下面的示例:

        >>> tring=['a', 'b', 'c', 'd', 'e']
        >>> len(tring)
        5
        >>> del tring[1]
        >>> print(’刪除第二個元素:', tring)
        刪除第二個元素: ['a','c','d','e']
        >>> len(tring)
        4

由上面的示例看到,可以使用del刪除列表中的元素。上面的示例使用del刪除了tring列表中的第二個元素,刪除元素后,原來有5個元素的列表變成只有4個元素的列表了。使用del除了可以刪除列表中的字符,也可以刪除列表中的數字,輸入如下:

        >>> num=[1,2,3]
        >>> len(num)
        3
        >>> del num[2]
        >>> print(’刪除第3個元素后:', num)
        刪除第3個元素后:[1, 2]
        >>> len(num)
        2

上面的輸出結果已經從數字列表中刪除了對應的數字。

除了刪除列表中的元素,del還能用于刪除其他元素,具體在后續章節會做詳細介紹。

4.分片賦值

分片賦值是列表一個強大的特性。先看下面的示例:

        >>> list(’女排奪冠了’)
        [’女’, ’排’, ’奪’, ’冠’, ’了’]
        >>> boil=list(’女排奪冠了’)
        >>> boil
        [’女’, ’排’, ’奪’, ’冠’, ’了’]
        >>> show=list('hi, boy')
        >>> show
        ['h', 'i', ', ', 'b', 'o', 'y']
        >>> show[3:]=list('man')
        >>> show
        ['h', 'i', ', ', 'm', 'a', 'n']

由上述示例可以看出,可以通過分片賦值直接對列表進行變更。示例中我們通過分片操作變更了編號3之后位置的元素,即將boy替換為man了。

上述示例中引入了一個新函數——list()函數。list()函數可以直接將字符串轉換為列表。該函數的一個功能就是根據字符串創建列表,有時這么操作會很方便。List()函數不僅適用于字符串,所有類型的序列它都適用。

除了上面展示的功能,分片賦值還有什么強大的功能呢?先看下面的示例:

        >>> greeting=list('hi')
        >>> greeting
        ['h', 'i']
        >>> greeting[1:]=list('ello')
        >>> greeting
        ['h', 'e', 'l', 'l', 'o']

我們分析一下,前面給greeting賦的值是['h', 'i'],后面通過分片賦值操作將編號1之后的元素變更了,即將編號1位置的元素替換為e了,但是編號2之后沒有元素,怎么能操作成功呢?并且一直操作到編號為4的位置,這怎么可以?

這就是分片賦值另一個強大的功能,可以使用與原序列不等長的序列將分片替換。

還有沒有其他功能呢?請看下面的示例:

        >>> field=list('ae')
        >>> field
        ['a', 'e']
        >>> field [1:1]=list('bcd')
        >>> field
        ['a', 'b', 'c', 'd', 'e']
        >>> boil=list(’女排奪冠了’)
        >>> boil
        [’女’, ’排’, ’奪’, ’冠’, ’了’]
        >>> boil[2:2]=list('2016年奧運會’)
        >>> boil
        [’女’, ’排’, '2', '0', '1', '6', ’年’, ’奧’, ’運’, ’會’, ’奪’, ’冠’, ’了’]

從上面的示例可以看出,可以在不替換任何原有元素的情況下在任意位置插入新元素。讀者可自行嘗試在上面示例的其他位置進行操作。

當然,上面的示例程序只是“替換”了一個空分片,實際操作是插入一個序列。

通過該示例是否想起了前面的append()方法,不過分片賦值比append()方法強大多了,append()方法只能在列表尾部增加元素,而分片賦值可以在任意位置增加元素。

看到這里,是否同時想起了前面刪除元素的操作,分片賦值是否支持類似刪除的功能呢?是的,支持類似刪除的功能。下面我們證實一下這個猜想。

        >>> field=list('abcde')
        >>> field
        ['a','b','c','d','e']
        >>> field[1:4]=[]
        >>> field
        ['a', 'e']
        >>> boil=list(’女排2016年奧運會奪冠了’)
        >>> boil
        [’女’, ’排’, '2', '0', '1', '6', ’年’, ’奧’, ’運’, ’會’, ’奪’, ’冠’, ’了’]
        >>> boil[2:10]=[]
        >>> boil
        [’女’, ’排’, ’奪’, ’冠’, ’了’]
        >>> del field[1:4]
        >>> field
        ['a', 'e']

從上面示例可以看到,使用了前面插入操作的逆操作證實我們的猜想。刪除和插入一樣,可以對一個序列中任意位置的元素進行刪除。

所以通過分片賦值刪除元素也是可行的,并且分片賦值刪除的功能和del刪除的操作結果是一樣的。

3.2.2 嵌套列表

前面介紹的都是單層的列表,列表是否可以嵌套呢?我們做如下嘗試:

        >>> field=['a', 'b', 'c']
        >>> field
        ['a', 'b', 'c']
        >>> num=[1,2,3]
        >>> num
        [1, 2, 3]
        >>> mix=[field, num]
        >>> mix
        [['a', 'b', 'c'], [1, 2, 3]]
        >>> mix[0]
        ['a', 'b', 'c']
        >>> mix[1]
        [1, 2, 3]

由上面的操作結果得知,在列表中可以嵌套列表,嵌套的列表取出后還是列表。

3.2.3 列表方法

我們之前的章節介紹了函數,本節介紹一個與函數密切相關的概念——方法。

方法是與對象有緊密聯系的函數,對象可能是列表、數字,也可能是字符串或其他類型的對象。方法的調用方式前面有一個示例,調用語法如下:

對象.方法(參數)

由上面的語法和前面append()方法的示例可知:方法的定義方式是將對象放到方法名之前,兩者之間用一個點號隔開,方法后面的括號中可以根據需要帶上參數。除了語法上有一些不同,方法調用和函數調用很相似。

列表中有count、index、sort等比較常用的方法,下面逐一進行介紹。

1. append

該方法前面已經介紹過,功能是在列表的末尾添加新對象。

使用方式為:

        list.append(obj)

2. count count()方法用于統計某個元素在列表中出現的次數。

count()方法的語法如下:

list.count(obj)

此語法中list代表列表,obj代表列表中統計的對象。

使用該方法的示例如下:

        >>> field=list('hello, world')
        >>> field
        ['h', 'e', 'l', 'l', 'o', ', ', 'w', 'o', 'r', 'l', 'd']
        >>>print(’列表field中,字母o的個數:', field.count('o'))      #統計列表中的字符個數
        列表field中,字母o的個數: 2
        >>> print(’列表field中,字母l的個數:', field.count('l'))
        列表field中,字母l的個數: 3
        >>> print(’列表field中,字母a的個數:', field.count('a'))
        列表field中,字母a的個數: 0
        >>> listobj = [123, 'hello', 'world', 123]
        >>> listobj = [26, 'hello', 'world', 26]
        >>>print(’數字26 的個數:', listobj.count(26))
        數字26 的個數: 2
        >>> print('hello的個數:', listobj.count('hello'))#統計字符串個數
        hello的個數: 1
        >>> ['a', 'c', 'a', 'f', 'a'].count('a')
        3
        >>> mix=[[1,3],5,6, [1,3],2, ]
        >>> print(’嵌套列表mix中列表[1,3]的個數為:', mix.count([1,3]))
        嵌套列表mix中列表[1,3]的個數為: 2

3. extend

extend()方法用于在列表末尾一次性追加另一個序列中的多個值(用新列表擴展原來的列表)。

extend()方法的語法如下:

list.extend(seq)

此語法中list代表列表,seq代表元素列表。

使用該方法的示例如下:

        >>> a=['hello', 'world']
        >>> b=['python', 'is', 'funny']
        >>> a.extend(b)
        >>> a
        ['hello', 'world', 'python', 'is', 'funny']

以上操作結果看起來很像連接操作。extend()方法和序列相加有什么區別呢?我們先看看下面的示例:

        >>> a=['hello', 'world']
        >>> b=['python', 'is', 'funny']
        >>> a+b
        ['hello', 'world', 'python', 'is', 'funny']
        >>> a
        ['hello', 'world']

從輸出的結果可以看出,兩個示例中a和b賦值都是一樣的,但第一個示例中輸出a的值和第二個示例中輸出a的值不一樣。

由此我們得出,extend()方法和序列相加的主要區別是:extend()方法修改了被擴展的序列,如前面的a;原始的連接操作會返回一個全新的列表,如上面的示例,返回的是一個包含a和b副本的新列表,而不會修改原始的變量。

當然,上述示例也可以用前面學習的分片賦值實現相同的結果,輸入如下:

        >>> a=['hello', 'world']
        >>> b=['python', 'is', 'funny']
        >>> a[len(a):]=b
        >>> a
        ['hello', 'world', 'python', 'is', 'funny']

可以看到,輸出結果和使用extend()方法一樣,不過看起來沒有extend()方法易懂,因此不會選擇這個方案。

4. index

index()方法用于從列表中找出某個值第一個匹配項的索引位置。

index()方法的語法如下:

list.index(obj)

此語法中list代表列表,obj代表查找的對象。

使用該方法的示例如下:

        >>> field=['hello', 'world', 'python', 'is', 'funny']
        >>> print('hello的索引位置為:', field.index('hello'))
        hello的索引位置為: 0
        >>> print('python的索引位置為:', field.index('python'))
        python的索引位置為: 2
        >>> print('abc的索引位置為:', field.index('abc'))
        Traceback (most recent call last):
          File "<pyshell#21>", line 1, in <module>
            print('abc的索引位置為:', field.index('abc'))
        ValueError: 'abc' is not in list

由上面的示例看到,搜索單詞hello,會發現它在索引號為0的位置;搜索單詞python,它在索引號為2的位置,索引得到的位置跟元素在序列中的位置一樣。如果搜索列表中不存在字符串,操作結果就會出錯,所以對于不在列表中的元素,用index()方法操作時會報錯。

5. insert

insert()方法用于將對象插入列表。

insert()方法的語法如下:

list.insert(index, obj)

此語法中list代表列表,index代表對象obj需要插入的索引位置,obj代表要插入列表中的對象。

使用該方法的示例如下:

        >>> num=[1,2,3]
        >>> print(’插入之前的num:', num)
        插入之前的num: [1, 2, 3]
        >>> num.insert(2, ’插入位置在2之后,3之前’)
        >>> print(’插入之后的num:', num)
        插入之后的num: [1, 2,’插入位置在2之后,3之前’, 3]

由上面的示例看到,insert()方法操作挺方便的。

與extend()方法一樣,insert()方法的操作也可以使用我們前面學習的分片賦值實現。

        >>> num=[1,2,3]
        >>> print(’插入之前的num:', num)
        插入之前的num: [1, 2, 3]
        >>> num[2:2]=[’插入位置在2之后,3之前’]
        >>>print('插入之后的num:',num)
        插入之后的num: [1, 2,’插入位置在2之后,3之前’, 3]

輸出結果和insert操作的結果一樣,但看起來沒有使用insert容易理解,應該不會選擇這個方案。

6. pop

pop()方法用于移除列表中的一個元素(默認最后一個元素),并且返回該元素的值。

pop()方法的語法如下:

list.pop(obj=list[-1])

此語法中list代表列表,obj為可選擇的參數,代表要移除列表元素的對象。

使用該方法的示例如下:

        >>> field=['hello', 'world', 'python', 'is', 'funny']
        >>>field.pop()  #不傳參數,默認移除最后一個元素
        'funny'
        >>> print(’移除元素后的field:', field)
        移除元素后的field: ['hello','world','python','is']
        >>>field.pop(3)  #移除編號為3的元素
        'is'
        >>> print(’移除元素后的field:', field)
        移除元素后的field: ['hello','world','python']
        >>> field.pop(0)
        'hello'
        >>> print(’移除元素后的field:', field)
        移除元素后的field: ['world','python']

由上面的示例看到,調用pop方法移除元素時,在交互模式下會告知我們移除了哪個元素,如上面示例中的funny、is。移除funny時未傳參數,默認移除最后一個;is的移除則是根據傳入的編號3進行的。

注意 pop方法是唯一一個既能修改列表又能返回元素值(除了None)的列表方法。

使用pop方法可以實現一種常見的數據結構——棧。

棧的原理就像堆放盤子一樣,一次操作一個盤子,要將若干盤子堆成一堆,只能在一個盤子的上面放另一個盤子;要拿盤子時,只能從頂部一個一個往下拿,最后放入的盤子是最先被拿的。棧也是這樣,最后放入棧的最先被移除,稱為LIFO(Last In First Out),即后進先出。

棧中的放入和移除操作有統一的稱謂——入棧(push)和出棧(pop)。Python沒有入棧方法,但可以使用append方法代替。pop方法和append方法的操作結果恰好相反,如果入棧(或追加)剛剛出棧的值,最后得到的結果就不會變,例如以下操作:

        >>> num=[1,2,3]
        >>>num.append(num.pop())        #追加默認出棧的值
        >>> print('num追加默認出棧值的操作結果:', num)
        num追加默認出棧值的操作結果: [1, 2, 3]

由上面的操作結果看到,通過追加默認出棧的值得到的列表和原來是一樣的。

7. remove

remove()方法用于移除列表中某個值的第一個匹配項。

remove()方法的語法如下:

list.remove(obj)

此語法中list代表列表,obj為列表中要移除的對象。

使用該方法的示例如下:

        >>> field=[’女排’, ’精神’, ’中國’, ’精神’, ’學習’, ’精神’]
        >>> print(’移除前列表field:', field)
        移除前列表field: [’女排’,’精神’,’中國’,’精神’,’學習’,’精神’]
        >>> field.remove(’精神’)
        >>> print(’移除后列表field:', field)
        移除后列表field: [’女排’,’中國’,’精神’,’學習’,’精神’]
        >>>field.remove('abc')  #刪除列表中不存在的元素
        Traceback (most recent call last):
          File "<pyshell#71>", line 1, in <module>
            field.remove('abc')
        ValueError: list.remove(x): x not in list

由上面的輸出結果看到,只有第一次出現的值被移除了,第二次之后出現的值沒有被移除。上面的列表中有3個“精神”,調用移除方法后,刪除了第一個,后面兩個仍然存在。

同時,操作移除列表中不存在的值是不行的,系統會告知移除的對象不在列表中。

有一點需要了解的是:remove是一個沒有返回值的原位置元素變更方法,它修改了列表卻沒有返回值,與pop方法正好相反。

8. reverse

reverse()方法用于反向列表中的元素。

reverse()方法的語法如下:

list.reverse()

此語法中list代表列表,該方法不需要傳入參數。

使用該方法的示例如下:

        >>> num=[1,2,3]
        >>> print(’列表反轉前num:', num)
        列表反轉前num: [1,2,3]
        >>> num.reverse()
        >>> print(’列表反轉后:', num)
        列表反轉后: [3, 2, 1]

由上面的輸出結果看到,該方法改變了列表但不返回值(和前面的remove一樣)。

說明 擴展: 如果需要對一個序列進行反向迭代,那么可以使用reversed函數。這個函數并不返回列表,而是返回一個迭代器(Iterator)對象(該對象在后面會詳細介紹),可以通過list函數把返回的對象轉換為列表,例如:

                >>> num=[1,2,3]
                >>> print(’使用reversed函數翻轉結果:', list(reversed(num)))
                使用reversed函數翻轉結果: [3, 2, 1]

輸出結果對原序列反向迭代了。

9. sort

sort()方法用于對原列表進行排序,如果指定參數,就使用參數指定的比較方法進行排序。

sort()方法的語法如下:

list.sort(func)

此語法中list代表列表,func為可選參數。如果指定該參數,就會使用該參數的方法進行排序。

使用該方法的示例如下:

        >>> num=[5,8,1,3,6]
        >>> num.sort()
        >>> print('num調用sort方法后:', num)
        num調用sort方法后: [1, 3, 5, 6, 8]

由上面輸出的結果得知,sort方法改變了原來的列表,而不是簡單的返回一個已排序的列表副本。

我們前面學習過幾個改變列表卻不返回值的方法(如append),不能將操作結果賦給一個變量,這樣的行為方式很合常理。但當用戶需要一個排好序的列表副本,同時又保留原有列表不變時,可能會做如下操作:

        >>> num=[5,8,1,3,6]
        >>> n=num.sort()
        >>> print(’變量n的結果是:', n)
        變量n的結果是: None
        >>> print(’列表num排序后的結果是:', num)
        列表num排序后的結果是: [1, 3, 5, 6, 8]

輸出結果怎么和我們預期的不一樣呢?因為sort方法修改了列表num,但是返回的是空值,所以我們最后得到的是已排序的num和值為None的n。該想法正確的實現方式是先把num的副本賦值給n,然后對n進行排序,操作如下:

        >>> num=[5,8,1,3,6]
        >>>n=num                    #直接將列表num賦值給n
        >>> n.sort()
        >>> print(’變量n的結果是:', n)
        變量n的結果是: [1, 3, 5, 6, 8]
        >>>print('num的結果是:', num)     #num也被排序了
        num的結果是: [1, 3, 5, 6, 8]
        >>> num=[5,8,1,3,6]
        >>>n=num[:]                  #將列表num切片后賦值給n
        >>> n.sort()
        >>> print(’變量n的結果是:', n)
        變量n的結果是: [1, 3, 5, 6, 8]
        >>>print('num的結果是:', num)     #num保持原樣
        num的結果是: [5, 8, 1, 3, 6]

由上面的執行結果可以看到,若不將原列表(如列表num)分片后賦值給另一個變量(如n),則兩個列表都會被排序,這樣簡單的賦值后,兩個列表都指向同一個列表。由此提醒進行該操作時要記得對原列表分片。

如reverse方法一樣,sort方法也有一個有同樣功能的函數——sorted函數。該函數可以直接獲取列表的副本進行排序,使用方式如下:

        >>> num=[5,8,1,3,6]
        >>> n=sorted(num)
        >>> print(’變量n的操作結果是:', n)
        變量n的操作結果是: [1, 3, 5, 6, 8]
        >>>print('num的結果是:', num)     #num保持原樣
        num的結果是: [5, 8, 1, 3, 6]

執行結果和前面操作的一樣。sorted函數可以用于任何序列,返回結果都是一個列表。例如下面的操作:

        >>> sorted('python')
        ['h', 'n', 'o', 'p', 't', 'y']
        >>> sorted('321')
        ['1', '2', '3']

10. clear

clear()方法用于清空列表,類似于del a[:]。

clear()方法的語法如下:

list.clear()

此語法中list代表列表,不需要傳入參數。

使用該方法的示例如下:

        >>> field=['study', 'python', 'is', 'happy']
        >>> field.clear()
        >>> print('field調用clear方法后的結果:', field)
        field調用clear方法后的結果: []

由操作結果看到,clear方法會清空整個列表,調用該方法進行清空很簡單,但也要小心,因為一不小心就可能把整個列表都清空了。

11. copy

copy()方法用于復制列表,類似于a[:]。

copy()方法的語法如下:

list.copy()

此語法中list代表列表,不需要傳入參數。

使用該方法的示例如下:

        >>> field=['study', 'python', 'is', 'happy']
        >>> copyfield=field.copy()
        >>> print(’復制操作結果:', copyfield)
        復制操作結果: ['study', 'python', 'is', 'happy']

操作結果和該方法的意思一樣,是原原本本的拷貝操作。

12.高級排序

如果希望元素能按特定方式進行排序(不是sort方法默認的按升序排列元素),就可以自定義比較方法。

sort方法有兩個可選參數,即key和reverse。要使用它們,就要通過名字指定,我們稱之為關鍵字參數。例如下面的示例:

        >>> field=['study', 'python', 'is', 'happy']
        >>>field.sort(key=len)                #按字符串由短到長排序
        >>> field
        >>>field.sort(key=len, reverse=True)      #按字符串由長到短排序,傳遞兩個參數
        >>> field
        ['python', 'study', 'happy', 'is']
        ['is', 'study', 'happy', 'python']
        >>> num=[5,8,1,3,6]
        >>>num.sort(reverse=True)             #排序后逆序
        >>>num
        [8, 6, 5, 3, 1]

由上面的操作結果可知,sort方法帶上參數后的操作是很靈活的,可以根據自己的需要靈活使用該方法。關于自定義函數,后續章節會有更詳細的介紹。

主站蜘蛛池模板: 龙门县| 齐齐哈尔市| 宜春市| 永寿县| 克拉玛依市| 濉溪县| 五寨县| 资兴市| 娄底市| 巴塘县| 秀山| 揭西县| 沙坪坝区| 乌拉特后旗| 元朗区| 读书| 仙游县| 阿巴嘎旗| 福建省| 武胜县| 贵溪市| 堆龙德庆县| 松阳县| 敦化市| 孟村| 新乐市| 丰城市| 丽江市| 乌鲁木齐县| 台南县| 台东市| 绥宁县| 双城市| 漠河县| 佛山市| 青河县| 峨眉山市| 台前县| 香港| 铜鼓县| 怀仁县|