<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 第二章 列表和元組 > 來源:http://www.cnblogs.com/Marlowes/p/5293195.html > 作者:Marlowes 本章將引入一個新的概念:_數據結構_。數據結構是通過某種方式(例如對元素進行編號)組織在一起的數據元素的集合,這些數據元素可以是數字或者字符,甚至可以是其他數據結構。在Python中,最基本的數據結構是_序列_(sequence),序列中的每個元素被分配一個序號——即元素的位置,也稱為_索引_。第一個索引是`0`,第二個則是`1`,以此類推。 _注:日常生活中,對某些東西計數或者編號的時候,可能會從`1`開始。所以Python使用的編號機制可能看起來很奇怪,但這種方法其實非常自然。在后面的章節中可以看到,這樣做的一個原因是也可以從最后一個元素開始計數;序列中的最后一個元素標記為`-1`,倒數第二個元素為`-2`,以此類推。這就意味著我們可以從第一個元素向前或向后計數了,第一個元素位于最開始,索引為`0`.使用一段時間后,讀者就會習慣于這種計數方式了。_ 本章首先對序列作一個概覽,接下來講解對所有序列(包括元組和列表)都通用的操作。這些操作也同樣適用于字符串。盡管下一章才會全面介紹有關字符串操作的內容,但是本章的一些例子已經用到了字符串操作。 在完成了基本介紹后,會開始學習如何使用列表,同時看看它有什么特別之處。然后討論元組。元組除了不能更改之外,其他的性質和列表都很類似。 ## 2.1 序列概述 Python包含6中內建的序列,本章重點討論最常用的兩種類型:_列表_和_元組_。其他的內建序列類型有字符串(將在下一章再次討論)、`Unicode`字符串、`buffer`對象和`xrange`對象。 列表和元組的主要卻別在于:列表可以修改,元組則不能。也就是說如果要根據要求來添加元素,那么列表可能會更好用;而處于某些原因,序列不能修改的時候,使用元組則更為合適。使用后者通常是技術性的,它與Python內部的運作方式有關。這也是內建函數會返回元組的原因。一般來說,在自己編寫的程序中,幾乎在所有的情況下都可以用列表代替元組(第四章將會介紹一個需要注意的例外情況:使用元組作為字典的鍵。在這種情況下,因為鍵不可更改,所以就不能使用列表)。 在需要操作一組數值的時候,序列很好用。可以用序列表示數據庫中一個人的信息——第1個元素是姓名,第2個元素是年齡。根據上述內容編寫一個列表(列表的各個元素通過逗號分隔,寫在方括號中),如下所示: ``` >>> info = ["XuHoo", 19] ``` 同時,序列也可以包含其他的序列,因此,構建如下的一個人員信息的列表也是可以的,這個列表就是你的數據庫: ``` >>> user_1 = ["XuHoo", 19] >>> user_2 = ["Marlowes", 19] >>> database = [user_1, user_2] >>> database [['XuHoo', 19], ['Marlowes', 19]] ``` _注:Python之中還有一種名為容器(container)的數據結構。容器基本上是包含到其他對象的任意對象。序列(例如列表和元組)和映射(例如字典)是兩類主要的容器。序列中的每個元素都有自己的編號,而映射中的每個元素則有一個名字(也稱為鍵)。在第四章會介紹更多有關映射的知識。至于既不是序列也不是映射的容器類型,集合(`set`)就是一個例子,請參見第十章的相關內容。_ ## 2.2 通用序列操作 所有序列類型都可以進行某些特定的操作。這些操作包括:_索引(indexing)、分片(slicing)、加(adding)、乘(multiplying)_以及檢查某個元素是否屬于序列的成員_(成員資格)。_除此之外,Python還有計算序列長度、找出最大元素和最小元素的內建函數。 _注:本節有一個重要的操作沒有提到——迭代(iteration)。對序列進行迭代的意思是:依次對序列中的每個元素重復執行某些操作。更多信息請參見5.5節。_ ### 2.2.1 索引 序列中的所有元素都是有編號的——從`0`開始遞增。這些元素可以通過編號分別訪問,如下例所示: ``` >>> greeting = "Hello" >>> greeting[0] 'H' ``` _注:字符串就是一個由字符組成的序列。索引`0`指向第1個元素,在這個例子中就是字母`H`。_ 這就是_索引_。可以通過索引獲取元素。所有序列都可以通過這種方式進行索引。使用負數索引時,Python會從右邊,也就是從最后1個元素開始計數。最后1個元素的位置編號是`-1`(不是`-0`,因為那會和第1個元素重合): ``` >>> greeting[-1] 'o' ``` 字符串字面值(就此而言,其他序列字面量亦可)能夠直接使用索引,而不需要一個變量引用它們。兩種做法的效果是一樣的: ``` >>> "Hello"[-1] # String 'o' >>> ["H", "e", "l", "l", "o"][-1] # List 'o' ``` 如果一個函數調用返回一個序列,那么可以直接對返回結果進行索引操作。例如,假設你只對用戶輸入年份的第四個數字感興趣,那么,可以進行如下操作: ``` >>> fourth = raw_input("Year: ")[3] Year: 1997 >>> fourth '7' ``` 代碼清單2-1是一個示例程序,它要求輸入年、月(1~12的數字)、日(1~31),然后打印出相應日期的月份名稱,等等。 ``` 1 #!/usr/bin/env python 2 # coding=utf-8 3 4 # 根據給定的年月日,以數字形式打印出日期 5 months = [ 6 "January", 7 "February", 8 "March", 9 "April", 10 "May", 11 "June", 12 "July", 13 "August", 14 "September", 15 "October", 16 "November", 17 "December" 18 ] 19 20 # 以1~31的數字作為結尾的列表 21 endings = ["st", "nd", "rd"] + 17 * ["th"] \ 22 + ["st", "nd", "rd"] + 7 * ["th"] \ 23 + ["st"] 24 25 year = raw_input("Year: ") 26 month = raw_input("Month(1~12): ") 27 day = raw_input("Day(1~31): ") 28 29 month_number = int(month) 30 day_number = int(day) 31 32 # 記得要將月份和天數減1,以獲得正確的索引 33 month_name = months[month_number - 1] 34 ordinal = day + endings[day_number - 1] 35 36 print month_name + " " + ordinal + ", " + year ``` Code_Listing 2-1 以下是程序執行的一部分結果: ``` Year: 1997 Month(1~12): 9 Day(1~31): 10 September 10th, 1997 ``` ### 2.2.2 分片 與使用索引來訪問單個元素類似,可以使用_分片操作_來訪問一定范圍內的元素。分片通過冒號隔開的兩個索引來實現: ``` >>> tag = '<a href="http://www.python.org">Python web site</a>' >>> tag[9:30] 'http://www.python.org' >>> tag[32:-4] 'Python web site' ``` 分片操作對于提取序列的一部分是很用的。而編號在這里顯得尤為重要。第1個索引是要提取的第1個元素的編號,而最后的索引則是分片之后剩余部分的第1個元素的編號。 ``` >>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> numbers[3:6] [4, 5, 6] >>> numbers[0:1] [1] ``` 簡而言之,分片操作的實現需要提供兩個索引作為邊界,第1個索引的元素是包含在分片內的,而第2個則不包含在分片內。 1\. 優雅的捷徑 假設需要訪問最后3個元素(根據先前的例子),那么當然可以進行顯示的操作: ``` >>> numbers[7:10] [8, 9, 10] ``` 現在,索引`10`指向的是第11個元素——這個元素并不存在,卻是在最后一個元素之后(為了讓分片部分能夠包含列表的最后一個元素,必須提供最后一個元素的下一個元素所對應的索引作為邊界)。明白了嗎? 現在,這樣的做法是可行的。但是,如果需要從列表的結尾開始計數呢? ``` >>> numbers[-3:-1] [8, 9] ``` 看來并不能以這種方式訪問最后的元素。那么使用索引`0`作為最后一步的下一步操作所使用的元素,結果又會怎么樣呢? ``` >>> numbers[-3:0] [] ``` 這并不是我們所要的結果。實際上,只要分片中最左邊的索引比它右邊的晚出現在序列中(在這個例子中是倒數第3個比第1個晚出現),結果就是一個空的序列。幸好,可以使用一個捷徑:如果分片所得部分包括序列結尾的元素,那么,只需置空最后一個索引即可。 ``` >>> numbers[-3:] [8, 9, 10] ``` 這種方法同樣適用于序列開始的元素: ``` >>> numbers[:3] [1, 2, 3] ``` 實際上,如果需要復制整個序列,可以將_兩個_索引都置空: ``` >>> numbers[:] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` 代碼清單2-2是一個小程序,它會提示輸入URL(假設它的形式為 http://www.somedomainname.com ),然后提取域名。 ``` 1 #!/usr/bin/env python 2 # coding=utf-8 3 4 # 對http://www.something.com形式的URL進行分割 5 6 url = raw_input("Please enter the URL: ") 7 domain = url[11:-4] 8 9 print "Domain name: " + domain ``` Code_Listing 2-2 以下是程序運行的示例: ``` Please enter the URL: http://www.python.org Domain name: python ``` 2.更大的步長 進行分片的時候,分片的開始和結束點需要進行指定(不管是直接還是間接)。而另外一個參數(在Python2.3加入到內建類型)——步長(step length)——通常都是隱式設置的。在普通的分片中,步長是`1`——分片操作就是按照這個步長逐個遍歷序列的元素,然后返回開始和結束點之間的所有元素。 ``` >>> numbers[0:10:1] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` 在這個例子中,分片包含了另外一個數字。沒錯,這就是步長的顯示設置。如果步長被設置為比1大的數,那么就會跳過某些元素。例如,步長設為2的分片包括的是從頭開始到結束每隔1個的元素。 ``` >>> numbers[0:10:2] [1, 3, 5, 7, 9] >>> numbers[3:6:3] [4] ``` 之前提及的捷徑也可以使用。如果需要將每4個元素中的第1個提取出來,那么只要將步長設置為`4`即可: ``` >>> numbers[::4] [1, 5, 9] ``` 當然,步長不能為`0`(那不會執行),但步長可以是_負數_,此時分片從右到左提取元素: ``` >>> numbers[8:3:-1] [9, 8, 7, 6, 5] >>> numbers[10:0:-2] [10, 8, 6, 4, 2] >>> numbers[0:10:-2] [] >>> numbers[::-2] [10, 8, 6, 4, 2] >>> numbers[5::-2] [6, 4, 2] >>> numbers[:5:-2] [10, 8] ``` 在這里要得到正確的分片結果需要動些腦筋。開始點的元素(最左邊的元素)包括在結果之中,而結束點的元素(最右邊的元素)則不在分片之內。當使用一個負數作為步長時,必須讓開始點(開始索引)_大于_結束點。在沒有明確指定開始點和結束點的時候,正負數的使用可能會帶來一些混淆。不過在這種情況下Python會進行正確的操作:對于一個正數步長,Python會從序列的頭部開始向右提取元素,直到最后一個元素;而對于負數步長,則是從序列的尾部開始向左提取元素,直到第一個元素。 ### 2.2.3 序列相加 通過使用加運算符可以進行序列的連接操作: ``` >>> [1, 2, 3] + [4, 5, 6] [1, 2, 3, 4, 5, 6] >>> "Hello, " + "world!" 'Hello, world!' >>> [1, 2, 3] + "wrold!" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "str") to list ``` 正如錯誤信息所提示的,列表和字符串是無法連接在一起的,盡管它們都是序列。簡單來說,兩種相同類型的序列才能進行連接操作。 ### 2.2.4 乘法 用數字`x`乘以一個序列會生成新的序列,而在新的序列中,原來的序列將被重復`x`次。 ``` >>> "Python" * 5 'PythonPythonPythonPythonPython' >>> [19] * 10 [19, 19, 19, 19, 19, 19, 19, 19, 19, 19] ``` None、空列表和初始化 空列表可以簡單地通過兩個中括號進行表示(`[]`)——里面什么東西都沒有。但是,如果想創建一個占用十個元素空間,卻不包括任何有用內容的列表,又該怎么辦呢?可以像前面那樣使用`[19]*10`,或者使用`[0]*10`,這會更加實際一些。這樣就生成了一個包括10個0的列表。然而,有時候可能會需要一個值來代表空值——意味著沒有在里面放置任何元素。這個時候就需要使用`None`。`None`是一個Python的內建值,它的確切含義是“這里什么也沒有”。因此,如果想初始化一個長度為`10`的列表,可以按照下面的例子來實現: ``` >>> sequence = [None] * 10 >>> sequence [None, None, None, None, None, None, None, None, None, None] ``` 代碼清單2-3的程序會在屏幕上打印一個由字符組成的“盒子”,而這個“盒子”在屏幕上居中而且能根據用戶輸入的句子自動調整大小。 代碼可能看起來很復雜,但只使用基本的算法——計算出有多少個空格、破折號等字符,然后將它們放置到合適的位置即可。 ``` 1 #!/usr/bin/env python 2 # coding=utf-8 3 4 # 以正確的寬度在居中的“盒子”內打印一個句子 5 6 # 注意,整數除法運算符(//)只能用在Python2.2以及后續的版本,在之前的版本中,只能使用普通除法(/) 7 8 sentence = raw_input("Sentence: ") 9 10 screen_width = 80 11 text_width = len(sentence) 12 box_width = text_width + 6 13 left_margin = (screen_width - box_width) // 2 14 15 print 16 print " " * left_margin + "+" + "-" * (box_width - 2) + "+" 17 print " " * left_margin + "| " + " " * text_width + " |" 18 print " " * left_margin + "| " + sentence + " |" 19 print " " * left_margin + "| " + " " * text_width + " |" 20 print " " * left_margin + "+" + "-" * (box_width - 2) + "+" 21 print ``` Code_Listing 2-3 下面是該例子的運行情況: ``` Sentence: He's a very naughty boy! +----------------------------+ | | | He's a very naughty boy! | | | +----------------------------+ ``` ### 2.2.5 成員資格 為了檢查一個值是否在序列中,可以使用`in`運算符。該運算符和之前已經討論過的(例如`+`、`*`運算符)有一點不同。這個運算符檢查某個條件是否為真,然后返回相應的值:條件為真返回`True`,條件為假返回`False`。這樣的運算符叫做_布爾運算符_,而返回的值叫做_布爾值_。第五章的條件語句部分會介紹更多關于布爾表達式的內容。 以下是一些使用了in運算符的例子: ``` >>> permissions = "rw" >>> "w" in permissions True >>> "x" in permissions False >>> users = ["mlh", "foo", "bar"] >>> raw_input("Please enter your user name: ") in users # 用戶名存在 Please enter your user name: mlh True >>> raw_input("Please enter your user name: ") in users # 用戶名不存在 Please enter your user name: Marlowes False >>> subject = "$$$ Get rich now!!! $$$" >>> "$$$" in subject True ``` 最初的兩個例子使用了成員資格測試分別來檢查`"w"`和`"x"`是否出現在字符串`permissions`中。在UNIX系統中,這兩行代碼可以作為查看文件可寫和可執行權限的腳本。接下來的例子則是檢查所提供的用戶名是否存在用戶列表中。如果程序需要執行某些安全策略,那么這個檢查就派上用場了(在這種情況下,可能還需要使用密碼)。最后一個例子可以作為垃圾郵件過濾器的一部分,它可以檢查字符串`subject`是否包含字符串`"$$$"`。 _注:最后一個檢查字符串是否包含`"$$$"`的例子有些不同。一般來說,`in`運算符會檢查每一個對象是否為某個序列(或者是其他數據集合)的成員(也就是元素)。然后,字符串唯一的成員或者元素就是它的字符。下面的例子就說明了這一點:_ ``` >>> "P" in "Python" True ``` _實際上,在早期的Python版本中,以上代碼是唯一能用于字符串成員資格檢查的方法——也就是檢查某個字符是否存在于一個字符串中。如果嘗試去檢查更長的子字符串(例如"$$$"),那么會得到一個錯誤信息(這個操作會引發TypeError,即類型錯誤)。為了實現這個功能,我們必須使用相關的字符串方法。第三章會介紹更多相關的內容。但是從Python2.3起,`in`運算符也能實現這個功能了。_ 代碼清單2-4給出了一個查看用戶輸入的用戶名和PIN碼是否存在于數據庫(實際上是一個列表)中的程序。如果用戶名/PIN碼這一數值對存在于數據庫中,那么就在屏幕上打印`"Access granted"`(第一章已經提到過`if`語句,第五章還將對其進行全面講解)。 ``` 1 #!/usr/bin/env python 2 3 # 檢查用戶名和PIN碼 4 5 database = [ 6 ["albert", "123"], 7 ["dilbert", "3521"], 8 ["smith", "6542"], 9 ["jones", "5634"] 10 ] 11 12 username = raw_input("Please enter your username: ") 13 pin = raw_input("Please enter your PIN: ") 14 15 if [username, pin] in database: 16 print "Access granted" ``` Code_Listing 2-4 ### 2.2.6 長度、最小值和最大值 內建函數`len`、`min`和`max`非常有用。`len`函數返回序列中所包含元素的數量,`min`函數和`max`函數則分別返回序列中最大和最小元素(在第五章的“比較運算符”部分會更加詳細介紹對象比較的內容)。 ``` >>> numbers = [100, 34, 678] >>> len(numbers) 3 >>> max(numbers) 678 >>> min(numbers) 34 >>> max(2, 3) 3 >>> min(9, 3, 2, 5) 2 ``` 根據上述解釋,我們可以很容易地理解例子中的各個操作是如何實現的,除了最后兩個表達式可能會讓人有些迷惑。在這里,`max`函數和`min`函數的參數并不是一個序列,而是以多個數字直接作為參數。 ## 2.3 列表:Python的“苦力” 在前面的例子中已經用了很多次列表,它的強大之處不言而喻。本節會討論列表不同于元組和字符串的地方:列表是可變的——可以改變列表的內容,并且列表有很多有用的、專門的方法。 ### 2.3.1 list函數 因為字符串不能像列表一樣被修改,所以有時根據字符串創建列表會很有用。`list`函數(它實際上是一種_類型_而不是函數,但在這里兩者的區別并不重要)可以實現這個操作: ``` >>> list("Hello") ['H', 'e', 'l', 'l', 'o'] ``` 注意,`list`函數適用于所有類型的序列,而不只是字符串。 _注:可以用下面的表達式將一個由字符(如前面代碼中的)組成的列表轉換為字符串:_ ``` ''.join(somelist) ``` _在這里,`somelist`是需要轉換的列表。要了解這行代碼真正的含義,請參考第三章有關`join`函數的部分。_ ### 2.3.2 基本的列表操作 列表可以使用所有適用于序列的標準操作,例如索引、分片、連接和乘法。有趣的是,列表是可以修改的。本節會介紹一些可以改變列表的方法:_元素賦值、元素刪除、分片賦值以及列表方法_(請注意,并不是所有的列表方法都能真正地改變列表)。 1.改變列表:元素賦值 改變列表是很容易的,只需要使用第一章提到的普通賦值語句即可。然而,我們并不會使用`x=2`這樣的語句進行賦值,而是使用索引標記來為某個特定的、位置明確的元素賦值。如`x[1]=2`。 ``` >>> x = [1, 1, 1] >>> x[1] = 2 >>> x [1, 2, 1] ``` _注:不能為一個位置不存在的元素進行賦值。如果列表的長度為`2`,那么不能為索引為`100`的元素進行賦值。如果要那樣做,就必須創建一個長度為`101`(或者更長)的列表。請參考本章“`None`、空列表和初始化”一節。_ 2.刪除元素 從列表中刪除元素也很容易:使用`del`語句實現。 ``` >>> names = ["Alice", "Beth", "Cecil", "Dee-Dee", "Earl"] >>> del names[2] >>> names ['Alice', 'Beth', 'Dee-Dee', 'Earl'] ``` 注意`Cecil`是如何徹底消失的,并且列表的長度也從`5`變為了`4`。除了刪除列表中的元素,`del`語句還能用于刪除其他元素。它可以用于字典元素(請參考第四章)甚至是其他變量得刪除操作,有關這方面的詳細介紹,請參見第五章。 3.分片賦值 分片是一個非常強大的特性,分片賦值操作則更加顯現它的強大。 ``` >>> name = list("Perl") >>> name ['P', 'e', 'r', 'l'] >>> name[2:] = list("ar") >>> name ['P', 'e', 'a', 'r'] ``` 程序可以一次為多個元素賦值了。可能有的讀者會想:這有什么大不了的,難道就不能一次一個地賦嗎?當然可以,但是在使用分片賦值時,可以使用與原序列不等長的序列將分片替換: ``` >>> name = list("Perl") >>> name[1:] = list("ython") >>> name ['P', 'y', 't', 'h', 'o', 'n'] ``` 分片賦值語句可以在不需要替換任何原有元素的情況下_插入_新的元素: ``` >>> numbers = [1, 5] >>> numbers[1:1] = [2, 3, 4] >>> numbers [1, 2, 3, 4, 5] ``` 這個程序只是“替換”了一個空的分片,因此實際的操作是插入了一個序列。以此類推,通過分片賦值來刪除元素也是可行的。 ``` >>> numbers [1, 2, 3, 4, 5] >>> numbers[1:4] = [] >>> numbers [1, 5] ``` 上面的例子結果和`del numbers[1:4]`的一樣。接下來請讀者自己嘗試利用1之外的步長,甚至是負數進行分片吧。 ### 2.3.3 列表方法 之前的章節中已經介紹了什么是函數,那么現在來看看另外一個與函數密切相關的概念——_方法。_ 方法是一個與某些對象有緊密聯系的函數,對象可能是列表、數字,也可能是字符串或者其他類型的對象。一般來說,方法可以這樣進行調用: _對象.方法(參數)_ 除了對象被放置到方法名之前,并且兩者之間用一個點號隔開,方法調用與函數調用很類似。第七章將對方法到底是什么進行更詳細的解釋。列表提供了幾個方法,用于檢查或者修改其中的內容。 1\. `append` `append`方法用于在列表末尾追加新的對象: ``` >>> lst = [1, 2, 3] >>> lst.append(4) >>> lst [1, 2, 3, 4] ``` 為什么我選擇了如此糟糕的變量名`lst`,而不是使用`list`來表示一個列表呢?原因在于`list`是一個內建函數(實際上,從Python2.2開始,`list`就是一個類型而不是函數了。(`tuple`和`str`也是如此)如果想了解完整的說明,請參見9.3.2節)。如果使用`list`作為變量名,我就無法調用`list`函數了。根據給定的應用程序可以定義更好的變量名,像`lst`這樣的變量名是毫無意義的。所以,如果需要定義一個價格列表,那么就應該使用`prices`、`prices_of_eggs`,或者`pricesOfEggs`作為變量名。 注意,下面的內容很重要:`append`方法和其他一些方法類似,只是在恰當位置修改原來的列表。這意味著,它不是簡單地返回一個修改過的新列表——而是直接修改原來的列表。一般來說這正是你想要的,但是在某些情況下,這樣也會帶來其他麻煩。在本章稍后講述`sort`方法時,我將再次討論這個問題。 2\. `count` `count`方法統計某個元素在列表中出現的次數: ``` >>> ["to", "be", "or", "not", "to", "be"].count("to") 2 >>> x = [[1, 2], 1, 1, [2, 1, [1, 2]]] >>> x.count(1) 2 >>> x.count([1, 2]) 1 ``` 3\. `extend` `extend`方法可以在列表的末尾一次性追加另一個序列中的多個值。換句話說,可以用新的列表擴展原有的列表: ``` >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> a.extend(b) >>> a [1, 2, 3, 4, 5, 6] ``` 這個操作看起來很像連接操作,兩者最主要的區別在于:`extend`方法修改了被擴展的序列(在這個例子中,就是`a`)。而原始的連接操作則不然,它會返回一個全新的列表: ``` >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> a + b [1, 2, 3, 4, 5, 6] >>> a [1, 2, 3] ``` 你可以看到連接的列表與之前例子中被擴展的列表是一樣的,但是這一次它并沒有被修改。這是因為原始的連接操作創建了一個包含`a`和`b`副本的新列表。如果需要如下例所示的操作,那么連接操作的效率會比`extend`方法低。 ``` >>> a = a + b ``` 同樣,這里也不是一個原位置操作,它并不會修改原來的列表。 我們可以使用分片賦值來實現相同的結果: ``` >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> a[len(a):] = b >>> a [1, 2, 3, 4, 5, 6] ``` 雖然這么做是可行的,但是代碼的可讀性就不如使用`extend`方法了。 4\. `index` `index`方法用于從列表中找出某個值第一個匹配項的索引位置: ``` >>> knights = ["We", "are", "the", "knights", "who", "say", "ni"] >>> knights.index("who") 4 >>> knights.index("herring") Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: 'herring' is not in list ``` 當搜索單詞`who`的時候,就會發現它在索引號為`4`的位置。然而,當搜索`"herring"`的時候,就會引發一個異常,因為這個單詞沒有被找到。 5\. `insert` `insert`方法用于將對象插入列表中: ``` >>> numbers = [1, 2, 3, 5, 6, 7] >>> numbers.insert(3, "four") >>> numbers [1, 2, 3, 'four', 5, 6, 7] ``` 與`extend`方法一樣,`insert`方法的操作也可以用分片賦值來實現。 ``` >>> numbers = [1, 2, 3, 5, 6, 7] >>> numbers[3:3] = ["four"] >>> numbers [1, 2, 3, 'four', 5, 6, 7] ``` 這樣做有點新奇,但是它的可讀性絕對不如`insert`方法。 6\. `pop` `pop`方法會移除列表中的一個元素(默認是最后一個),并且返回該元素的值: ``` >>> x = [1, 2, 3] >>> x.pop() 3 >>> x [1, 2] >>> x.pop(0) 1 >>> x [2] ``` _注:`pop`方法是唯一一個既能修改列表又返回元素值(除了`None`)的列表方法。_ 使用`pop`方法可以實現一種常見的數據結構——_棧_。棧的原理就像堆放盤子那樣。只能在頂部放盤子,同樣,也只能從頂部拿走一個盤子。最后被放入棧堆的最先被移除(這個原則成為LIFO,即_后進先出_)。 對于上述的兩個棧操作(放入和移出),它們有大家都認可的稱謂——_入棧_(`push`)和_出棧_(`pop`)。Python沒有_入棧_方法,但可以使用`append`方法來代替。`pop`方法和`append`方法的操作結果恰好相反,如果_入棧_(或者追加)剛剛_出棧_的值,最后得到的結果還是原來的棧。 ``` >>> x = [1, 2, 3] >>> x.append(x.pop()) >>> x [1, 2, 3] ``` _注:如果需要實現一個先進先出(FIFO)的隊列(`queue`),那么可以使用`insert(0, ...)`來代替`append`方法。或者,也可以繼續使用`append`方法,但必須用`pop(0`)來代替`pop()`。更好的解決方案是使用`collection`模塊中的`deque`對象。要了解更詳細的信息,請參見第十章_ 7\. `remove` `remove`方法用于移除列表中某個值的第一個匹配項: ``` >>> x = ["to", "be", "or", "not", "to", "be"] >>> x.remove("be") >>> x ['to', 'or', 'not', 'to', 'be'] >>> x.remove("bee") Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: list.remove(x): x not in list ``` 可以看到:只有第一次出現的值被移除了,而不存在于列表中的值(比如例子中的`"bee"`)是不會移除的。 值得注意的是,`remove`是一個沒有返回值的原位置改變的方法。它修改了列表卻沒有返回值,這與`pop`方法相反。 8\. `reverse` `reverse`方法將列表中的元素反向存放(我猜你們對此不會特別驚訝): ``` >>> x = [1, 2, 3] >>> x.reverse() >>> x [3, 2, 1] ``` 請注意,該方法也改變了列表但不反悔值(就像`remove`和`sort`)。 _注:如果需要對一個序列進行反向迭代,那么可以使用`reversed`函數。這個函數并不返回一個列表,而是返回一個迭代器(`iterator`)對象(第九章介紹了更多關于迭代器的內容)。盡管如此,使用`list`函數把返回值的對象轉換成列表也是可行的:_ ``` >>> x = [4, 6, 2, 1, 7, 9] >>> list(reversed(x)) [9, 7, 1, 2, 6, 4] ``` 9.sort `sort`方法用于在原位置(從Python2.3開始,`sort`方法使用了固定的排序算法)對列表進行排序。在“原位置排序”意味著改變原來的列表,從而讓其中的元素未能按一定的順序排列,而不是簡單地返回一個已排序的列表副本。 ``` >>> x = [4, 6, 2, 1, 7, 9] >>> x.sort() >>> x [1, 2, 4, 6, 7, 9] ``` 前面介紹過了幾個改變列表卻不返回值的方法,在大多數情況下這樣的行為方式是很合常理的(例如`append`方法)。但是,`sort`方法的這種行為方式需要重點講解一下,因為很多人都被`sort`方法弄糊涂了。當用戶需要一個排好序的列表副本,同時又保留原有列表不變的時候,問題就出現了。為了實現這個功能,我們自然而然就想到了如下的做法(實際是錯誤的): ``` >>> x = [4, 6, 2, 1, 7, 9] >>> y = x.sort() # Don't do this! >>> print y None ``` 因為`sort`方法修改了x卻返回了空值,那么最后得到的是已排序的`x`以及值為`None`的`y`。實現這個功能的正確方法是,首先把`x`的副本賦值給`y`,然后對`y`進行排序,如下例所示: ``` >>> x = [4, 6, 2, 1, 7, 9] >>> y = x[:] >>> y.sort() >>> x [4, 6, 2, 1, 7, 9] >>> y [1, 2, 4, 6, 7, 9] ``` 再次調用`x[:]`得到的是包含了x所有元素的分片,這是一種很有效率的賦值整個列表的方法。只是簡單地把`x`賦值給`y`是沒有用的,因為這樣做就讓`x`和`y`都指向同一個列表了。 ``` >>> x = [4, 6, 2, 1, 7, 9] >>> y = x >>> y.sort() >>> x [1, 2, 4, 6, 7, 9] >>> y [1, 2, 4, 6, 7, 9] ``` 另一種獲取已排序的列表副本的方法是,使用`sorted`函數: ``` >>> x = [4, 6, 2, 1, 7, 9] >>> y = sorted(x) >>> x [4, 6, 2, 1, 7, 9] >>> y [1, 2, 4, 6, 7, 9] ``` 這個函數實際上可以用于任何序列,卻總是返回一個列表(`sorted`函數可以用于任何可迭代的對象。有關可迭代對象的詳細內容,請參見第九章): ``` >>> sorted("Python") ['P', 'h', 'n', 'o', 't', 'y'] ``` 如果想把一些元素按相反的順序排序,可以先使用`sort`(或者`sorted`),然后再調用`reverse`方法(注意,需要分兩次對列表調用`sort`方法以及`reverse`方法。如果打算通過`x.sort().reverse()`來實現,會發現行不通,因為`x.sort()`返回的是`None`。當然,`sorted(x).reverse()`是正確的做法),或者也可以使用`reverse`參數,下一節將對此進行描述。 10.高級排序 如果希望元素能按照特定的方式進行排序(而不是`sort`函數默認的方式,即根據Python的默認排序規則按升序排列元素,第五章內對此進行詳解),那么可以通過`compare(x, y)`的形式自定義_比較函數_。`compare(x, y)`函數會在` x < y` 時返回負數,在 `x > y` 時返回正數,如果 `x = y` 則返回0(根據你的定義)。定義好該函數之后,就可以提供給`sort`方法作為參數了。內建函數`cmp`提供了比較函數的默認實現方式: ``` >>> cmp(42, 32) 1 >>> cmp(99, 100) -1 >>> cmp(19, 19) 0 >>> numbers = [5, 2, 9, 7] >>> numbers.sort(cmp) >>> numbers [2, 5, 7, 9] ``` `sort`方法有另外兩個可選的參數——`key`和`reverse`。如果要使用它們,那么就要通過名字來指定(這叫做_關鍵字參數_,請參見第六章以了解更多的內容)。參數`key`與參數`cmp`類似——必須提供一個在排序過程中使用的函數。然而,該函數并不是直接用來確定對象的大小,而是為每個元素創建一個_鍵_,然后所有元素根據鍵來排序。因此,如果要根據元素的長度進行排序,那么可以使用`len`作為鍵函數: ``` >>> x = ["aardvark", "abalone", "acme", "add", "aerate"] >>> x.sort(key=len) >>> x ['add', 'acme', 'aerate', 'abalone', 'aardvark'] ``` 另一個關鍵字參數`reverse`是簡單的布爾值(`True`或者是`False`。第五章會講述更詳細的內容),用來指明列表是否要進行反向排序。 ``` >>> x = [4, 6, 2, 1, 7, 9] >>> x.sort(reverse=True) # True為反向排序 >>> x [9, 7, 6, 4, 2, 1] >>> x = [4, 6, 2, 1, 7, 9] >>> x.sort(reverse=False) # Flase為正向排序 >>> x [1, 2, 4, 6, 7, 9] ``` `cmp`、`key`、`reverse`參數都可以用于`sorted`函數。在多數情況下,為`cmp`或`key`提供自定義函數是非常有用的。第六章將會講述如何定義自己的函數。 注:如果想了解更多有關于排序的內容,可以查看Andrew Dalke的 “Sorting Mini-HOWTO”,鏈接是:http://wiki.python.org/moin/HowTo/Sorting 。 ## 2.4 元組:不可變序列 元組與列表一樣,也是一種序列。唯一的不同是元組不能修改(元組和列表在技術實現上有一些不同,但是在實際使用時,可能不會注意到。而且,元組沒有像列表一樣的方法。)。(你可能注意到了,字符串也是如此)創建元組的語法很簡單:如果你用逗號分隔了一些值,那么你就自動創建了元組。 ``` >>> 1, 2, 3 (1, 2, 3) ``` 元組也是(大部分時候是)通過圓括號括起來的: ``` >>> (1, 2, 3) (1, 2, 3) ``` 空元組可以用沒有包含內容的兩個圓括號來表示: ``` >>> () () ``` 那么如何實現包括一個值的元組呢。實現方法有些奇特——必須加個逗號,即使只有一個值: ``` >>> 42 42 >>> 42, (42,) >>> (42,) (42,) ``` 最后兩個例子生成了一個長度為1的元組,而第一個例子根本不是元組。逗號是很重要的,只添加圓括號也是沒用的:`(42)`和`42`是完全一樣的。但是,一個逗號卻能徹底地改變表達式的值: ``` >>> 3 * (40 + 2) 126 >>> 3 * (40 + 2,) (42, 42, 42) ``` ### 2.4.1 tuple函數 `tuple`函數的功能與`list`函數基本上是一樣的:以一個序列作為參數并把它轉換為元組(`tuple`并不是真正的函數——而是一種類型。在之前講述`list`函數的時候,我也提到了這一點。同時,與`list`函數一樣,目前也可以放心地忽略這一點)。如果參數就是元組,那么該參數就會被原樣返回: ``` >>> tuple([1, 2, 3]) (1, 2, 3) >>> tuple("abc") ('a', 'b', 'c') >>> tuple((1, 2, 3)) (1, 2, 3) ``` ### 2.4.2 基本元組操作 元組其實并不復雜——除了創建元組和訪問元組元素之外,也沒有太多其他的操作,可以參照其他類型的序列來實現: ``` >>> x = 1, 2, 3 >>> x[1] 2 >>> x[0:2] (1, 2) ``` 元組的分片還是元組,就像列表的分片還是列表一樣。 ### 2.4.3 那么,意義何在 現在你可能會想到底有誰會需要像元組那樣的不可變序列呢?難道就不能在不改變其中內容的時候堅持只用列表嗎?一般來說這是可行的。但是由于以下兩個重要的原因,元組是不可替代的。 √ 元組可以在映射(和集合的成員)中當做鍵使用——而列表則不行(本章導言部分提到過映射,更多有關映射的內容,請參看第四章)。 √ 元組作為很多內建函數和方法的返回值存在,也就是說你必須對元組進行處理。只要不嘗試修改元組,那么,“處理”元組在絕大多數情況下就是把它們當做列表來進行操作(除非需要使用一些元組沒有的方法,例如`index`和`count`)。 一般來說,列表可能更能滿足對序列的所有需求。 ## 2.5 小結 讓我們回顧本章所涵蓋的一些最重要的內容。 √ 序列。序列是一種數據結構,它包含的元素都進行了編號(從`0`開始)。典型的序列包括列表、字符串和元組。其中,列表是可變的(可以進行修改),而元組和字符串是不可變的(一旦創建了就是固定的)。通過分片操作可以訪問序列的一部分,其中分片需要兩個索引號來指出分片的起始和結束位置。要想改變列表,則要對相應的位置進行賦值,或者使用賦值語句重寫整個分片。 √ 成員資格。`in`操作符可以檢查一個值是否存在于序列(或者其他的容器)中。對字符串使用`in`操作符是一個特例,它可以查找子字符串。 √ 方法。一些內建類型(例如列表和字符串,元組則不在其中)具有很多有用的方法。這些方法有些像函數,不過它們與特定值聯系得更密切。方法是面向對象編程的一個重要的概念,稍后的第七章中會對其進行討論。 ### 2.5.1 本章的新函數 ``` cmp(x, y) 比較兩個值 len(seq) 返回序列的長度 list(seq) 把序列轉換成列表 max(args) 返回序列或者參數集合中的最大值 min(args) 返回序列或者參數集合中的最小值 reversed(seq) 對序列進行反向迭代 sorted(seq) 返回已排序的包含seq所有元素的列表 tuple(seq) 把序列轉換成元組 ``` ### 2.5.2 接下來學什么 序列已經介紹完了,下一章會繼續介紹由字符組成的序列,即_字符串_。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看