<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 第八章 字符串 字符串和整形、浮點數以及布爾值很不一樣。一個字符串是一個序列,意味著是對其他值的有序排列。在本章你將學到如何讀取字符串中的字符,你還會學到一些字符串相關的方法。 ## 8.1 字符串是序列 字符串就是一串有序的字符。你可以通過方括號操作符,每次去訪問字符串中的一個字符: ```py >>> fruit = 'banana' >>> letter = fruit[1] ``` 第二個語句選擇了 fruit 這個字符串的序號為 1 的字符,并把這個字符賦值給了 letter 這個變量。 (譯者注:思考一下這里的 letter 是一個什么類型的變量。) 方括號內的內容叫做索引。索引指示了你所指定的字符串中字符的位置(就跟名字差不多)。 但你可能發現得到的結果和你預期的有點不一樣: ```py >>> letter 'a' ``` 大多數人都認為 banana 的第『1』個字符應該是 b,而不是 a。但對于計算機科學家來說,索引是字符串從頭的偏移量,所以真正的首字母偏移量應該是 0. ```py >>> letter = fruit[0]>>> letter 'b' ``` 所以 b 就是字符串 banana 的第『0』個字符,而 a 是第『1』個,n 就是第『2』個了。 你可以在方括號內的索引中使用變量和表達式: ```py >>> i = 1 >>> fruit[i] 'a' >>> fruit[i+1] 'n' ``` 但要注意的事,索引的值必須是整形的。否則你就會遇到類型錯誤了: ```py >>> letter = fruit[1.5] TypeError: string indices must be integers ``` ## 8.2 len 長度 len 是一個內置函數,會返回一個字符串中字符的長度: ```py >>> fruit = 'banana' >>> len(fruit) 6 ``` 要得到一個字符串的最后一個字符,你可能會想到去利用 len 函數: ```py >>> length = len(fruit) >>> last = fruit[length] IndexError: string index out of range ``` 出現索引錯誤的原因就是 banana 這個字符串在第『6』個位置是沒有字母的。因為我們從 0 開始數,所以這一共 6 個字母的順序是 0 到 5 號。因此要得到最后一次字符,你需要在字符串長度的基礎上減去 1 才行: ```py >>> last = fruit[length-1] >>> last 'a' ``` 或者你也可以用負數索引,意思就是從字符串的末尾向前數幾位。fruit[-1]這個表達式給你最后一個字符,fruit[-2]給出倒數第二個,依此類推。 ## 8.3 用 for 循環遍歷字符串 很多計算過程都需要每次從一個字符串中拿一個字符。一般都是從頭開始,依次得到每個字符,然后做點處理,然后一直到末尾。這種處理模式叫遍歷。寫一個遍歷可以使用 while 循環: ```py index = 0 while index < len(fruit): letter = fruit[index] print(letter) index = index + 1 ``` 這個循環遍歷了整個字符串,然后它再把買一個字符顯示在一行上面。循環條件是 index 這個變量小于字符串 fruit 的長度,所以當 index 與字符串長度相等的時候,條件就不成立了,循環體就不運行了。最后一個字符被獲取的時候,index 正好是 len(fruit)-1,這就已經是該字符串的最后一個字符了。 下面就練習一下了,寫一個函數,接收一個字符串做參數,然后倒序顯示每一個字符,每行顯示一個。 另外一種遍歷的方法就是 for 循環了: ```py for letter in fruit: print(letter) ``` 每次循環之后,字符串中的下一個字符都會賦值給變量 letter。循環在進行到沒有字符剩余的時候就停止了。 下面的例子展示了如何使用級聯(字符串加法)以及一個 for 循環來生成一個簡單的序列(用字母表順序)。 在 Robert McCloskey 的一本名叫《Make Way for Ducklings》的書中,小鴨子的名字依次為:Jack, Kack, Lack, Mack, Nack, Ouack, Pack, 和 Quack。下面這個循環會依次輸出他們的名字: ```py prefixes = 'JKLMNOPQ' suffix = 'ack' for letter in prefixes: print(letter + suffix) ``` 輸出結果如下: ```py Jack Kack Lack Mack Nack Oack Pack Qack ``` 當然了,有點不準確的地方,因為有“Ouack”和 “Quack”兩處拼寫錯了。做個練習,修改一下程序,改正這個錯誤。 ## 8.4 字符串切片 字符串的一段叫做切片。從字符串中選擇一部分做切片,與選擇一個字符有些相似: ```py >>> s = 'Monty Python' >>> s[0:5] 'Monty' >>> s[6:12] 'Python' ``` [n:m]這種操作符,會返回字符串中從第『n』個到第『m』個的字符,包含開頭的第『n』個,但不包含末尾的第『m』個。這個設計可能有點違背直覺,但可能有助于想象這個切片在字符串中的方向,如圖 8.1。 ________________________________________ ![Figure 8.1](http://7xnq2o.com1.z0.glb.clouddn.com/ThinkPythonFigure8.1.png) Figure 8.1: Slice indices. ________________________________________ 如果你忽略了第一個索引(就是冒號前面的那個),切片會默認從字符串頭部開始。如果你忽略了第二個索引,切片會一直包含到最后一位: ```py >>> fruit = 'banana' >>> fruit[:3] 'ban' >>> fruit[3:] 'ana' ``` 如果兩個索引相等,得到的就是空字符串了,用兩個單引號來表示: ```py >>> fruit = 'banana' >>> fruit[3:3] '' ``` 空字符串不包含字符,長度為 0,除此之外,都與其他字符串是一樣的。 那么來練習一下,你覺得 fruit[:]這個是什么意思?在程序中試試吧。 ## 8.5 字符串不可修改 大家總是有可能想試試把方括號在賦值表達式的等號左側,試圖去更改字符串中的某一個字符。比如: ```py >>> greeting = 'Hello, world!' >>> greeting[0] = 'J' TypeError: 'str' object does not support item assignment ``` 『object』是對象的意思,這里指的是字符串類 string,然后『item』是指你試圖賦值的字符串中的字符。目前來說,一個對象就跟一個值差不多,但后續在第十章第十節我們再對這個定義進行詳細討論。 產生上述錯誤的原因是字符串是不能被修改的,這意味著你不能對一個已經存在的字符串進行任何改動。你頂多也就能建立一個新字符串,新字符串可以基于舊字符串進行一些改動。 ```py >>> greeting = 'Hello, world!' >>> new_greeting = 'J' + greeting[1:] >>> new_greeting 'Jello, world!' ``` 上面的例子中,對 greeting 這個字符串進行了切片,然后添加了一個新的首字母過去。這并不會對原始字符串有任何影響。(譯者注:也就是 greeting 這個字符串的值依然是原來的值,是不可改變的。) ## 8.6 搜索 下面這個函數是干啥的? ```py def find(word, letter): index = 0 while index < len(word): if word[index] == letter: return index index = index + 1 return -1 ``` 簡單來說,find 函數,也就是查找,是方括號操作符[]的逆運算。方括號是之道索引然后提取對應的字符,而查找函數是選定一個字符去查找這個字符出現的索引位置。如果字符沒有被報道,函數就返回-1。 這是我們見過的第一個返回語句位于循環體內的例子。如果 word[index]等于 letter,函數就跳出循環立刻返回。如果字符在字符串里面沒出現,程序正常退出循環并且返回-1。 這種計算-遍歷一個序列然后返回我們要找的東西的模式就叫做搜索了。 做個練習,修改一下 find 函數,加入第三個參數,這個參數為查找開始的字符串位置。 ## 8.7 循環和計數 下面這個程序計算了字母 a 在一個字符串中出現的次數: ```py word = 'banana' count = 0 for letter in word: if letter == 'a': count = count + 1 print(count) ``` 這一程序展示了另外一種計算模式,叫做計數。變量 count 被初始化為 0,然后每次在字符串中找到一個 a,就讓 count 加 1.當循環退出的時候,count 就包含了 a 出現的總次數。 做個練習,把上面的代碼封裝進一個名叫 count 的函數中,泛化一下,一遍讓他接收任何字符串和字幕作為參數。 然后再重寫一下這個函數,這次不再讓它遍歷整個字符串,而使用上一節中練習的三參數版本的 find 函數。 ## 8.8 字符串方法 字符串提供了一些方法,這些方法能夠進行很多有用的操作。方法和函數有些類似,也接收參數然后返回一個值,但語法稍微不同。比如,upper 這個方法就讀取一個字符串,返回一個全部為大寫字母的新字符串。 與函數的 upper(word)語法不同,方法的語法是 word.upper()。 ```py >>> word = 'banana' >>> new_word = word.upper() >>> new_word 'BANANA' ``` 這種用點號分隔的方法表明了使用的方法名字為 upper,使用這個方法的字符串的名字為 word。后面括號里面是空白的,表示這個方法不接收參數。 A method call is called an invocation;方法的調用被叫做——調用(譯者注:中文都混淆成調用,英文里面 invocation 和 invoke 都有祈禱的意思,和 call 有顯著的意義差別,但中文都混淆成調用,這種例子不勝枚舉,所以大家盡量多讀原版作品。);在這里,我們就說調用了 word 的 upper 方法。 結果我們發現 string 有一個方法叫做 find,跟我們寫過的函數 find 有驚人的相似: ```py >>> word = 'banana' >>> index = word.find('a') >>> index 1 ``` 在這里我們調用了 word 的 find 方法,然后給定了我們要找的字母 a 作為一個參數。 實際上,這個 find 方法比我們的 find 函數功能更通用;它不僅能查找字符,還能查找字符串: ```py >>> word.find('na') 2 ``` 默認情況下 find 方法從字符串的開頭來查找,不過可以給它一個第二個參數,讓它從指定位置查找: ```py >>> word.find('na', 3) 4 ``` 這是一個可選參數的例子;find 方法還能接收第三個參數,可以指定查找終止的位置: ```py >>> name = 'bob' >>> name.find('b', 1, 2) -1 ``` 這個搜索失敗了,因為 b 并沒有在索引 1 到 2 且不包括 2 的字符中間出現。搜索到指定的第三個變量作為索引的位置,但不包括該位置,這就讓 find 方法與切片操作符相一致。 ## 8.9 運算符 in in 這個詞在字符串操作中是一個布爾操作符,它讀取兩個字符串,如果前者的字符串為后者所包含,就返回真,否則為假: ```py >>> 'a' in 'banana' True >>> 'seed' in 'banana' False ``` 舉個例子,下面的函數顯示所有同時在 word1 和 word2 當中出現的字母: ```py def in_both(word1, word2): for letter in word1: if letter in word2: print(letter) ``` 選好變量名的話,Python 有時候讀起來就跟英語差不多。你讀一下這個循環,就能發現,『對第一個 word 當中的每一個字母 letter,如果這個字母也在第二個 word 當中出現,就輸出這個字母 letter。』 ```py >>> in_both('apples', 'oranges') a e s ``` ## 8.10 字符串比較 關系運算符對于字符串來說也可用。比如可以看看兩個字符串是不是相等: ```py if word == 'banana': print('All right, bananas.') ``` 其他的關系運算符可以來把字符串按照字母表順序排列: ```py if word < 'banana': print('Your word, ' + word + ', comes before banana.') elif word > 'banana': print('Your word, ' + word + ', comes after banana.') else: print('All right, bananas.') ``` Python 對大小寫字母的處理與人類常規思路不同。所有大寫字母都在小寫字母之前,所以順序上應該是:Your word,然后是 Pineapple,然后才是 banana。 一個解決這個問題的普遍方法是把字符串轉換為標準格式,比如都轉成小寫的,然后再進行比較。一定要記得哈,以免你遇到一個用 Pineapple 武裝著自己的家伙的時候手足無措。 ## 8.11 調試 使用索引來遍歷一個序列中的值的時候,弄清楚遍歷的開頭和結尾很不容易。下面這個函數用來對比兩個單詞,如果一個是另一個的倒序就返回真,但這個函數代碼中有兩處錯誤: ```py def is_reverse(word1, word2): if len(word1) != len(word2): return False i = 0 j = len(word2) while j > 0: if word1[i] != word2[j]: return False i = i+1 j = j-1 return True ``` 第一個 if 語句是檢查兩個詞的長度是否一樣。如果不一樣長,當場就返回假。對函數其余部分,我們假設兩個單詞一樣長。這里用到了守衛模式,在第 6 章第 8 節我們提到過。 i 和 j 都是索引:i 從頭到尾遍歷單詞 word1,而 j 逆向遍歷單詞 word2.如果我們發現兩個字母不匹配,就可以立即返回假。如果經過整個循環,所有字母都匹配,就返回真。 如果我們用這個函數來處理單詞『pots』和『stop』,我們希望函數返回真,但得到的卻是索引錯誤: ```py >>> is_reverse('pots', 'stop') ... File "reverse.py", line 15, in is_reverse if word1[i] != word2[j]: IndexError: string index out of range ``` 為了改正這個錯誤,第一步就是在出錯的那行之前先輸出索引的值。 ```py while j > 0: print(i, j) # print here if word1[i] != word2[j]: return False i = i+1 j = j-1 ``` 然后我再次運行函數,得到更多信息了: ```py >>> is_reverse('pots', 'stop') 0 4 ... IndexError: string index out of range ``` 第一次循環完畢的時候,j 的值是 4,這超出了『pots』這個字符串的范圍了(譯者注:應該是 0-3)。最后一個索引應該是 3,所以 j 的初始值應該是 len(word2)-1。 ```py >>> is_reverse('pots', 'stop') 0 3 1 2 2 1 True ``` 這次我們得到了正確的結果,但似乎循環只走了三次,這有點奇怪。為了弄明白帶到怎么回事,我們可以畫一個狀態圖。在第一次迭代的過程中,is_reverse 的框架如圖 8.2 所示。 ________________________________________ ![Figure 8.2](http://7xnq2o.com1.z0.glb.clouddn.com/ThinkPythonFigure8.2.png) Figure 8.2: State diagram. ________________________________________ 我通過設置變量框架中添加虛線表明,i 和 j 的值顯示在人物 word1and word2 拿許可證。 從這個圖上運行的程序,文件,更改這些值 I 和 J 在每一次迭代過程。發現并解決此函數中的二次錯誤。 ## 8.12 Glossary 術語列表 object: Something a variable can refer to. For now, you can use “object” and “value” interchangeably. >對象:一個值能夠指代的東西。目前為止,你可以把對象和值暫且作為一碼事來理解。 sequence: An ordered collection of values where each value is identified by an integer index. >序列:一系列值的有序排列,每一個值都有一個唯一的整數序號。 item: One of the values in a sequence. >元素:一列數值序列當中的一個值。 index: An integer value used to select an item in a sequence, such as a character in a string. In Python indices start from 0. >索引:一個整數值,用來指代一個序列中的特定一個元素,比如在字符串里面就指代一個字符。在 Python 里面索引從 0 開始計數。 slice: A part of a string specified by a range of indices. >切片:字符串的一部分,通過一個索引區間來取得。 empty string: A string with no characters and length 0, represented by two quotation marks. >空字符串:沒有字符的字符串,長度為 0,用兩個單引號表示。 immutable: The property of a sequence whose items cannot be changed. >不可更改:一個序列中所有元素不能被改變的性質。 traverse: To iterate through the items in a sequence, performing a similar operation on each. >遍歷:在一個序列中依次對每一個元素進行某種相似運算的過程。 search: A pattern of traversal that stops when it finds what it is looking for. >搜索:一種遍歷的模式,找到要找的內容的時候就停止。 counter: A variable used to count something, usually initialized to zero and then incremented. >計數:一種用來統計某種東西數量的變量,一般初始化為 0,然后逐次遞增。 invocation: A statement that calls a method. >方法調用:調用方法的語句。 optional argument: A function or method argument that is not required. >可選參數:一個函數或者方法中有一些參數是可選的,非必需的。 ## 8.13 練習 ### 練習 1 閱讀 [這里](http://docs.python.org/2/library/stdtypes.html#string-methods)關于字符串的文檔。你也許會想要試試其中一些方法,來確保你理解它們的意義。比如 strip 和 replace 都特別有用。 文檔的語法有可能不太好理解。比如在 find 這個方法中,方括號表示了可選參數。所以 sub 是必須的參數,但 start 是可選的,如果你包含了 start,end 就是可選的了。 ### 練習 2 字符串有個方法叫 count,與咱們在 8.7 中寫的 count 函數很相似。 閱讀一下這個方法的文檔,然后寫一個調用這個方法的代碼,統計一下 banana 這個單詞中 a 出現的次數 。 ### 練習 3 字符串切片可以使用第三個索引,作為步長來使用;步長的意思就是取字符的間距。一個步長為 2 的意思就是每隔一個取一個字符;3 的意思就是每次取第三個,以此類推。 ```py >>> fruit = 'banana' >>> fruit[0:5:2] 'bnn' ``` 步長如果為-1,意思就是倒序讀取字符串,所以[::-1]這個切片就會生成一個逆序的字符串了。 使用這個方法把練習三當中的 is_palindrome 寫成一個一行代碼的版本。 ### 練習 4 下面這些函數都試圖檢查一個字符串是不是包含小寫字母,但他們當中肯定有些是錯的。描述一下每個函數真正的行為(假設參數是一個字符串)。 ```py def any_lowercase1(s): for c in s: if c.islower(): return True else: return False def any_lowercase2(s): for c in s: if 'c'.islower(): return 'True' else: return 'False' def any_lowercase3(s): for c in s: flag = c.islower() return flag def any_lowercase4(s): flag = False for c in s: flag = flag or c.islower() return flag def any_lowercase5(s): for c in s: if not c.islower(): return False return True ``` ### 練習 5 凱撒密碼是一種簡單的加密方法,用的方法是把每個字母進行特定數量的移位。對一個字母移位就是把它根據字母表的順序來增減對應,如果到末尾位數不夠就從開頭算剩余的位數,『A』移位 3 就是『D』,而『Z』移位 1 就是『A』了。 要對一個詞進行移位,要把每個字母都移動同樣的數量。比如『cheer』這個單詞移位 7 就是『jolly』,而『melon』移位-10 就是『cubed』。在電影《2001 太空漫游》中,飛船的電腦叫 HAL,就是 IBM 移位-1。 寫一個名叫 rotate_word 的函數,接收一個字符串和一個整形為參數,返回將源字符串移位該整數位得到的新字符串。 你也許會用得上內置函數 ord,它把字符轉換成數值代碼,然后還有個 chr 是用來把數值代碼轉換成字符。字母表中的字母都被編譯成跟字母表中同樣的順序了,所以如下所示: ```py >>> ord('c') - ord('a') 2 ``` c 是字母表中的第『2』個(譯者注:從 0 開始數哈)的位置,所以上述結果是 2。但注意:大寫字母的數值代碼是和小寫的不一樣的。 網上很多有冒犯意義的玩笑都是用 ROT13 加密的,也就是移位 13 的凱撒密碼。如果你不太介意,找一下這些密碼解密一下吧。[樣例代碼](http://thinkpython2.com/code/rotate.py).
                  <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>

                              哎呀哎呀视频在线观看