本文內容全部出自《Python基礎教程》第二版,在此分享自己的學習之路。 lxx___歡迎轉載:http://www.cnblogs.com/Marlowes/p/5312236.htmllxx___ Created on Xu Hoo 讀者已經知道了什麼是字元串,也知道如何創建它們。利用索引和分片 ...
本文內容全部出自《Python基礎教程》第二版,在此分享自己的學習之路。
______歡迎轉載:http://www.cnblogs.com/Marlowes/p/5312236.html______
Created on Xu Hoo
讀者已經知道了什麼是字元串,也知道如何創建它們。利用索引和分片訪問字元串中的單個字元也已經不在話下了。那麼本章將會介紹如何使用字元串格式化其他的值(如列印特殊格式的字元串),並簡單瞭解一下利用字元串的分割、連接、搜索等方法能做些什麼。
3.1 基本字元串操作
所有標準的序列操作(索引、分片、乘法、判斷成員資格、求長度、取最小值和最大值)對字元串同樣適用,上一章已經講述了這些操作。但是,請記住字元串都是不可變的。因此,如下所示的項或分片賦值都是不合法的:
>>> website = "http://www.python.org" >>> website[-3:] = "com" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment
3.2 字元串格式化:精簡版
如果初次接觸Python編程,那麼Python提供的所有字元串格式化功能可能用不到太多。因此,這裡只簡單介紹一些主要的內容。如果讀者對細節感興趣,可以參見下一章,否則可以直接閱讀3.4節。
字元串格式化使用字元串格式化操作符(這個名字還是很恰當的)即百分號%來實現。
註:%也可以用作模運算(求餘)操作符。
在%的左側放置一個字元串(格式化字元串),而右側則放置希望被格式化的值。可以使用一個值,如一個字元串或者數字,也可以使用多個值的元組或者下一章將會討論的字典(如果希望格式化多個值的話),這部分內容將在下一章進行討論。一般情況下使用元組:
>>> format = "Hello, %s. %s enough for ya?" >>> values = ("world", "Hot") >>> print format % values Hello, world. Hot enough for ya?
註:如果使用列表或者其他序列代替元組,那麼序列會被解釋為一個值。只有元組和字典(將在第4章討論)可以格式化一個以上的值。
格式化字元串的%s部分稱為轉換說明符(conversion specifier),它們標記了需要插入轉換值的位置。s表示值會被格式化為字元串——如果不是字元串,則會用str將其轉換為字元串。這個方法對大多數值都有效。其他轉換說明符請參見本章後面的表3-1.
註:如果要在格式化字元串裡面包括百分號,那麼必須使用%%,這樣Python就不會將百分號誤認為是轉換說明符了。
如果要格式化實數(浮點數),可以使用f說明轉換說明符的類型,同時提供所需要的精度:一個句點再加上希望保留的小數位數。因為格式化轉換說明符總是以表示類型的字元結束,所以精度應該放在類型字元前面:
>>> format = "Pi with three decimals: %.3f" >>> from math import pi >>> print format % pi Pi with three decimals: 3.142
模板字元串
string模塊提供另外一種格式化值的方法:模板字元串。它的工作方式類似於很多UNIX Shell里的變數替換。如下所示,substitute這個模板方法會用傳遞進來的關鍵字參數foo替換字元串中的$foo(有關關鍵字參數的詳細信息,請參看第六章):
>>> from string import Template >>> s = Template("$x, glorious $x!") >>> s.substitute(x="slurm") 'slurm, glorious slurm!'
如果替換欄位是單詞的一部分,那麼參數名就必須用括弧括起來,從而準確指明結尾:
>>> s = Template("It's ${x}tastic!") >>> s.substitute(x="slurm") "It's slurmtastic!"
可以使用$$插入美元符號:
>>> s = Template("Make $$ selling $x!") >>> s.substitute(x="slurm") 'Make $ selling slurm!'
除了關鍵字參數之外,還可以使用字典變數提供值/名稱對(參見第四章)。
>>> s = Template("A $thing must never $action.") >>> d = {} >>> d["thing"] = "gentleman" >>> d["action"] = "show his socks" >>> s.substitute(d) 'A gentleman must never show his socks.'
方法safe_substitute不會因缺少值或者不正確使用$字元而出錯(更多信息請參見Python庫參考手冊的4.1.2節)。
3.3 字元串格式化:完整版
格式化操作符的右操作數可以是任意類型,如果是元組或者映射類型(如字典),那麼字元串格式化將會有所不同。我們尚未涉及映射(如字典),在此先瞭解一下元組。第四章還會詳細介紹映射的格式化。
如果右操作數是元組的話,則其中的每一個元素都會被單獨格式化,每個值都需要一個對應的轉換說明符。
註:如果需要轉換的元組作為轉換表達式的一部分存在,那麼必須將它用圓括弧括起來,以避免出錯。
>>> "%s plus %s equals %s" % (1, 1, 2) '1 plus 1 equals 2' >>> "%s plus %s equals %s" % 1, 1, 2 # Lacks parentheses! Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: not enough arguments for format string
基本的轉換說明符(與此相對應的是完整的轉換說明符,也就是包括映射鍵的說明符,詳細內容參見第四章)包括以下部分。註意,這些項的順序是至關重要的。
(1)%字元:標記轉換說明符的開始。
(2)轉換標誌(可選): - 表示左對齊; + 表示在轉換值之前要加上正負號;“” (空白字元)表示整數之前保留空格;0表示轉換值若位數不夠則用0填充。
(3)最小欄位寬度(可選):轉換後的字元串至少應該具有該值指定的寬度。如果是*,則寬度會從值元組中讀出。
(4)點(.)後跟精度值(可選):如果轉化的是實數,精度值就表示出現在小數點後的位數。如果轉換的是字元串,那麼該數字就表示最大欄位寬度。如果是*,那麼精度將會從元組中讀出。
(5)轉換類型:參見表3-1。
表3-1 字元串格式化轉換類型
d, i 帶符號的十進位整數
o 不帶符號的八進位
u 不帶符號的十進位
x 不帶符號的十六進位(小寫)
X 不帶符號的十六進位(大寫)
e 科學計數法表示的浮點數(小寫)
E 科學計數法表示的浮點數(大寫)
f, F 十進位浮點數
g 如果指數大於-4或者小於精度值則和e相同,其他情況與f相同
G 如果指數大於-4或者小於精度值則和E相同,其他情況與F相同
C 單字元(接受整數或者單字元字元串)
r 字元串(使用repr轉換任意Python對象)
s 字元串(使用str轉換任意Python對象)
接下來幾個小節將對轉換說明符的各個元素進行詳細討論。
3.3.1 簡單轉換
簡單的轉換隻需要寫出轉換類型,使用起來很簡單:
>>> "Price of eggs: $%d" % 42 'Price of eggs: $42' >>> "Hexadecimal price of eggs: %x" % 42 'Hexadecimal price of eggs: 2a' >>> from math import pi >>> "Pi: %f..." %pi 'Pi: 3.141593...' >>> "Very inexact estimate of pi: %i" % pi 'Very inexact estimate of pi: 3' >>> "Using str: %s" % 42L 'Using str: 42' >>> "Using repr: %r" % 42L 'Using repr: 42L'
3.3.2 欄位寬度和精度
轉換說明符可以包括欄位寬度和精度。欄位寬度是轉換後的值所保留的最小字元個數,精度(對於數字轉換來說)則是結果中應該包含的小數位數,或者(對於字元串轉換來說)是轉換後的值所能包含的最大字元個數。
這兩個參數都是整數(首先是欄位寬度,然後是精度),通過點號(.)分隔。雖然兩個都是可選的參數,但如果只給出精度,就必須包含點號:
>>> "%10f" % pi # 欄位寬10 ' 3.141593' >>> "%10.2f" % pi # 欄位寬10,精度2 ' 3.14' >>> "%.2f" % pi # 精度2 '3.14' >>> "%.5s" % "Guido van Rossum" 'Guido'
可以使用*(星號)作為欄位寬度或者精度(或者兩者都是用*),此時數值會從元組參數中讀出:
>>> "%.*s" % (5, "Guido van Rossum") 'Guido'
3.3.3 符號、對齊和用0填充
在欄位寬度和精度值之前還可以放置一個“標誌”,該標誌可以是零、加號、減號或空格。零表示數字將會用0進行填充。
>>> "%010.2f" % pi '0000003.14'
註意,在010中開頭的那個0並不意味著欄位寬度說明符為八進位數,它只是個普通的Python數值。當使用010作為欄位寬度說明符的時候,表示欄位寬度為10,並且用0進行填充空位,而不是說欄位寬度為8:
>>> 010 8
減號(-)用來左對齊數值:
>>> "%-10.2f" % pi '3.14 '
可以看到,在數字的右側多出了額外的空格。
而空白("")意味著在正數前加上空格。這在需要對齊正負數時會很有用:
>>> print ("%+5d" % 10) + "\n" + ("%+5d" % -10) +10 -10
代碼清單3-1中的代碼將使用星號欄位寬度說明符來格式化一張包含水果價格的表格,表格的總寬度由用戶輸入。因為是由用戶提供信息,所以就不能在轉換說明符中將欄位寬度硬編碼。使用星號運算符就可以從轉換元組中讀出欄位寬度。
1 #!/usr/bin/env python 2 # coding=utf-8 3 4 # 使用給定的寬度列印格式化後的價格列表 5 6 width = input("Please enter width: ") 7 8 price_width = 10 9 item_width = width - price_width 10 11 header_format = "%-*s%*s" 12 format = "%-*s%*.2f" 13 14 print "=" * width 15 16 print header_format % (item_width, "Item", price_width, "Price") 17 18 print "-" * width 19 20 print format % (item_width, "Apples", price_width, 0.4) 21 print format % (item_width, "Pears", price_width, 0.5) 22 print format % (item_width, "Cantaloupes", price_width, 1.92) 23 print format % (item_width, "Dried Apricots (16 oz.)", price_width, 8) 24 print format % (item_width, "Prunes (4 lbs.)", price_width, 12) 25 26 print "=" * widthCode_Listing 3-1
以下是程式運行示例:
Please enter width: 35 =================================== Item Price ----------------------------------- Apples 0.40 Pears 0.50 Cantaloupes 1.92 Dried Apricots (16 oz.) 8.00 Prunes (4 lbs.) 12.00 ===================================
3.4 字元串方法
前面幾節已經介紹了很多列表的方法,字元串的方法還要豐富得多,這是因為字元串從string模塊中“繼承”了很多方法,而在早期版本的Python中,這些方法都是作為函數出現的(如果真的需要的話,還是能找到這些函數的)。
因為字元串的方法是實在太多,在這裡只介紹一些特別有用的。全部方法請參見附錄B。在字元串的方法描述中,可以在本章找到關聯到其他方法的參考(用“請參見”標記),或請參見附錄B。
但是字元串未死
儘管字元串方法完全來源於string模塊,但是這個模塊還包括一些不能作為字元串方法使用的常量和函數。maketrans函數就是其中之一,後面會將它和translate方法一起介紹。下麵是一些有用的字元串常量(對於此模塊的更多介紹,請參見Python庫參考手冊(http://python.org/doc/lib/module-string.html)的4.1節)。
√ string.digits:包含數字0~9的字元串。
√ string.letters:包含所有字母(大寫或小寫)的字元串。
√ string.lowercase:包含所有小寫字母的字元串。
√ string.printable:包含所有可列印字元的字元串。
√ string.punctuation:包含所有標點的字元串。
√ string.uppercase:包含所有大寫字母的字元串。
字母字元串常量(例如string.letters)與地區有關(也就是說,其具體值取決於Python所配置的語言)(在Python3.0中,string.letters和其相關內容都會被移除。如果需要則應該使用string.ascii_letters常量代替)。如果可以確定自己使用的ASCII,那麼可以在變數中使用ascii_首碼,例如string.ascii_letters。
3.4.1 find
find方法可以在一個較長的字元串中查找子串。它返回子串所在位置的最左端索引。如果沒有找到則返回-1。
>>> "With a moo-moo here, and a moo-moo there".find("moo") 7 >>> title = "Monty Python's Flying Circus" >>> title.find("Monty") 0 >>> title.find("Python") # 找到字元串 6 >>> title.find("Flying") 15 >>> title.find("Zirquss") # 未找到字元串 -1
在第二章中我們初始了成員資格,我們在subject中使用了"$$$"表達式建立了一個垃圾郵件過濾器。也可以使用find方法(Python2.3以前的版本中也可用,但是in操作符只能用來查找字元串中的單個字元):
>>> subject = "$$$ Get rich now!!! $$$" >>> subject.find("$$$") 0
註:字元串的find方法並不返回布爾值。如果返回的是0,則證明在索引0位置找到了子串。
這個方法還可以接收可選的起始點和結束點參數:
>>> subject = "$$$ Get rich now!!! $$$" >>> subject.find("$$$") 0 >>> subject.find("$$$", 1) # 只提供起始點 20 >>> subject.find("!!!") 16 >>> subject.find("!!!", 0, 16) # 提供起始點和結束點 -1
註意,由起始和終止值指定的範圍(第二個和第三個參數)包含第一個索引,但不包含第二個索引。這在Python中是個慣例。
附錄B:rfind、index、rindex、count、startswith、endswith。
3.4.2 join
join方法是非常重要的字元串方法,它是split方法的逆方法,用來連接序列中的元素:
>>> seq = [1, 2, 3, 4, 5] >>> sep = "+" >>> sep.join(seq) # 連接數字列表 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sequence item 0: expected string, int found >>> seq = ["1", "2", "3", "4", "5"] >>> sep.join(seq) # 連接字元串列表 '1+2+3+4+5' >>> dirs = "", "usr", "bin", "env" >>> "/".join(dirs) '/usr/bin/env' >>> print "C:" + "\\".join(dirs) C:\usr\bin\env
可以看到,需要被連接的序列元素都必須是字元串。註意最後兩個例子中使用了目錄的列表,而在格式化時,根據UNIX和DOS/Windows的約定,使用了不同的分隔符號(在DOS版本中還增加了驅動器名)。
請參見:split。
3.4.3 lower
lower方法返回字元串的小寫字母版。
>>> "Trondheim Hammer Dance".lower() 'trondheim hammer dance'
如果想要編寫“不區分大小寫”的代碼的話,那麼這個方法就派上用場了——代碼會忽略大小寫狀態。例如,如果想在列表中查找一個用戶名是否存在:列表包含字元串"gumby",而用戶輸入的是"Gumby",就找不到了:
>>> if "Gumby" in ["gumby", "smith", "jones"]: print "Found it!" ... >>>
如果存儲的是"Gumby"而用戶輸入"gumby"甚至是"GUMBY",結果也是一樣的。解決方法就是在存儲和搜索時把所有名字都轉換為小寫。代碼如下:
>>> name = "Gumby" >>> names = ["gumby", "smith", "jones"] >>> if name.lower() in names: print "Found it!" ... Found it!
請參見:translate。
附錄B:islower、capitalize、swapcase、title、istitle、upper、isupper。
標題轉換
和lower方法相關的是title方法(參見附錄B),它會將字元串轉換為標題——也就是所有單詞的首字母大寫,而其他字母小寫。但是它使用的單詞劃分方法可能會得到並不自然的結果:
>>> "that's all folks".title() "That'S All Folks"
再介紹另外一個string模塊的capwords函數:
>>> import string >>> string.capwords("that's all, folks") "That's All, Folks"
當然,如果要得到正確首字母大寫的標題(這要根據你的風格而定,可能要小寫冠詞、連詞及5個字母以下的介詞等),那麼還是得自己把握。
3.4.4 replace
replace方法返回某字元串的所有匹配項均被替換之後得到字元串。
>>> "This is a test".replace("is", "eez") 'Theez eez a test'
如果曾經用過文字處理程式中的“查找並替換”功能的話,就不會質疑這個方法的用處了。
請參見:translate。
附錄B:expandtabs。
3.4.5 split
這是一個非常重要的字元串方法,它是join的逆方法,用來將字元串分隔成序列。
>>> "1+2+3+4+5".split("+") ['1', '2', '3', '4', '5'] >>> "/usr/bin/env".split("/") ['', 'usr', 'bin', 'env'] >>> "Using the default".split() ['Using', 'the', 'default']
註意,如果不提供任何分隔符,程式會把所有空格作為分隔符(空格、製表、換行等)。
請參見:join。
附錄B:rsplit、splitlines。
3.4.6 strip
strip方法返回去除兩側(不包括內部)空格的字元串:
>>> " internal whitespace is kept ".strip() 'internal whitespace is kept'
它和lower方法一起使用的話就可以很方便的對比輸入的和存儲的值。讓我們回到lower部分中的用戶名的例子,假設用戶在輸入名字時無意中在名字後面加上了空格:
>>> names = ["gumby", "smith", "jones"] >>> name = "gumby " >>> if name in names: print "Found it!" ... >>> if name.strip() in names: print "Found it!" ... Found it!
也可以指定需要去除的字元,將它們列為參數即可。
>>> "*** SPAM * for * everyone!!! ***".strip(" *!") 'SPAM * for * everyone'
這個方法只會去除兩側的字元,所以字元串中的星號沒有被去掉。
附錄B:lstrip、rstrip。
3.4.7 translate
translate方法和replace方法一樣,可以替換字元串中的某些部分,但是和前者不同的是,translate方法只處理單個字元。它的優勢在於可以同時進行多個替換,有些時候比replace效率高得多。
使用這個方法的方式有很多(比如替換換行符或者其他因平臺而異的特殊字元)。但是讓我們考慮一個簡單的例子(很簡單的例子):假設需要將純正的英文文本轉換為帶有德國口音的版本。為此,需要把字元c替換為k把s替換為z。
在使用translate轉換之前,需要先完成一張轉換表。轉換表中是以某字元替換某字元的對應關係。因為這個表(事實上是字元串)有多達256個項目,我們還是不要自己寫了,使用string模塊裡面的maketrans函數就行。
maketrans函數接受兩個參數:兩個等長的字元串,表示第一個字元串中的每個字元都用第二個字元串中相同位置的字元替換。明白了嗎?來看一個簡單的例子,代碼如下:
>>> from string import maketrans >>> table = maketrans("cs", "kz")
轉換表中都有什麼
轉換表是包含替換ASCII字元集中256個字元的替換字母的字元串。
>>> table = maketrans("cs", "kz") >>> len(table) 256 >>> table[97:123] 'abkdefghijklmnopqrztuvwxyz' >>> maketrans("", "")[97:123] 'abcdefghijklmnopqrstuvwxyz'
正如你看到的,我已經把小寫字母部分的表提取出來了。看一下這個表和空轉換(沒有改變任何東西)中的字母表。空轉換包含一個普通的字母表,而在它前面的代碼中,字母c和s分別被替換為k和z。
創建這個表以後,可以將它用作translate方法的參數,進行字元串的轉換如下:
>>> "this is an incredible test".translate(table) 'thiz iz an inkredible tezt'
translate的第二個參數是可選的,這個參數是用來指定需要刪除的字元。例如,如果想要模擬一句語速超快的德國語,可以刪除所有空格:
>>> "this is an incredible test".translate(table, " ") 'thizizaninkredibletezt'
請參見:replace、lower。
3.5 小結
本章介紹了字元串的兩種非常重要的使用方式。
字元串格式化:求模操作符(%)可以用來將其他值轉換為包含轉換標誌的字元串,例如%s。它還能用來對值進行不同方式的格式化,包括左右對齊、設定欄位寬度以及精度值,增加符號(正負號)或者左填充數字0等。
字元串方法:字元串有很多方法。有些非常有用(比如split和join),有些則用的很少(比如istitle或者capitalize)。
3.5.1 本章的新函數
本章新涉及的函數如表3-2所示。
表3-2 本章的新函數
string.capwords(s[, sep]) 使用split函數分隔字元串s(以sep為分隔符),使用capitalize函數將分割得到的各單詞首字母大寫,並且使用join函數以sep為分隔符將各單詞連接起來。
string.maketrans(from, to) 創建用於轉換的轉換表。
3.5.2 接下來學什麼
列表、字元串和字典是Python中最重要的3種數據類型。列表和字元串已經學習過了,那麼下麵是什麼呢?下一章中的主要內容是字典,以及字典如何支持索引以及其他方式的鍵(比如字元串和元組)。字典也提供了一些方法,但是數量沒有字元串多。