字串幾乎是所有程式語言在專案開發過程中,涉及最多的一塊內容。大部分專案的執行結果,都需要以文字的形式展示給客戶,比如財務系統的總賬報表;電子遊戲的比賽結果,火車站的列車時刻表等。這些都是經過程式精密的計算、判斷和梳理,將我們想要的內容以文字形式直觀地展示出來。曾經流傳過這樣一句話:開發一個專案,基本上就是在不斷地處理字串。本小節學習重點如下:
數位之間的邏輯運算,範例程式碼如下:
a = 0
b = 1
c = 2
# and運運算元,只要有一個值為0,則結果為0,否則結果為最後一個非0數位
print(a and b) # 0
print(b and a) # 0
print(a and c) # 0
print(c and a) # 0
print(b and c) # 2
print(c and b) # 1
# or運運算元,只有所有值為0結果才為0,否則結果為第一個非0數位
print(a or b) # 1
print(a or c) # 2
print(b or c) # 1
問題:1 or 2、1 and 2、0 and 2 or 1 or 4、0 or False and 1、1 < (2==2)、1 < 2 == 2 分別輸出什麼?
在 Python 中,使用單引號 '
或雙引號 "
可以定義字串。語法格式如下:
'內容'
"內容"
單引號和雙引號常用於表示單行字串。也可以在字串中新增換行符 \n
間接定義多行字串。
程式輸出結果如下圖所示:
在使用單引號定義的字串中,可以直接包含雙引號,而不必進行跳脫;而在使用雙引號定義的字串中,可以直接包含單引號,而不必進行跳脫。即外單內雙,外雙內單。範例程式碼如下:
str1 = "I'm Amo, a teacher!"
str2 = 'I "am" Amo, a teacher!'
print(str1)
print(str2)
print(type(str1), type(str2))
程式執行結果如下:
思考:如何建立一個字串 I'm Amo
?
注意:使用 type()函數返回結果為 <class 'str'>
, 則資料型別為 str(字串)。並且 Python 不支援字元型別,單個字元也算一個字串。
單引號、雙引號定義多行字串時,需要新增換行符 \n
,而三引號不需要新增換行符,語法格式如下:
'''多行
字串'''
"""多行
字串"""
同時字串中可以包含單引號、雙引號、換行符、製表符,以及其他特殊字元,對於這些特殊字元不需要使用反斜槓 \
進行跳脫。另外,三引號中還可以包含註釋資訊。使用三引號定義一段 HTML 字串,這時使用三引號定義非常方便,如果使用跳脫字元逐個跳脫特殊字元就非常麻煩,如下:
str3 = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello World</h1>
</body>
<script>
console.log("amo is so cool~")
</script>
</html>
"""
三引號可以幫助開發人員從引號和跳脫字元的泥潭裡面解脫出來,確保字串的原始格式。三引號一般用於函數註釋、類註釋、定義 SQL 語句等,讀者可以在 Python 原始碼中看到大量三引號的應用,如下:
使用 str()
函數可以建立空字串,也可以將任意型別的物件轉換為字串。使用 str() 函數建立字串的不同形式:
str() 函數的返回值由型別 __str__
魔法方法決定。下面範例自定義一個 list 型別,定義 __str__
魔法方法的返回值為 list 字串表示,同時去掉左右兩側的中括號分隔符。如下:
class MyList(list): # 自定義list型別,繼承於list
def __init__(self, value): # 型別初始化函數
self.value = list(value) # 把接受的引數轉換為列表並儲存起來
def __str__(self):
# 把傳入的值轉換為字串,並去掉左右兩側的中括號分隔符
return str(self.value).replace("[", "").replace("]", "")
s = str(MyList([1, 2, 3]))
print(s)
字串的輸出:
print('hello world') # 直接輸出
name = 'Amo'
print(name) # 輸出變數
print('我的名字是%s' % name) # 格式化輸出
print(f'我的名字是{name}') # 格式化輸出
字串的輸入,在 Python 中,使用 input()
接收使用者輸入。
name = input('請輸入您的名字:')
print(f'您輸入的名字是{name}')
print(type(name))
password = input('請輸入您的密碼:')
print(f'您輸入的密碼是{password}')
print(type(password))
程式執行結果如下圖所示:
輸入的特點總結:
input
,等待使用者輸入,輸入完成之後才繼續向下執行。input
接收使用者輸入後,一般儲存到變數,方便使用。input
會把接收到的任意使用者輸入的資料都當做字串處理。跳脫字元
在 Python 字串中如果顯示特殊字元,必須經過跳脫才能夠顯示。例如,換行符需要使用 \n
表示,製表符需要使用 \t
表示,單引號需要使用 \'
,雙引號需要使用 \"
表示,等等。Python 可用的字元跳脫序列說明如下表所示:
轉 義 序 列 | 含 義 |
---|---|
\newline(下一行) | 忽略反斜槓和換行 |
\\ | 反斜槓(\) |
\’ | 單引號(’) |
\" | 雙引號(") |
\a | ASCII 響鈴(BEL) |
\b | ASCII 退格(BS) |
\f | ASCII 換頁(FF) |
\n | ASCII 換行(LF) |
\r | ASCII 回車(CR) |
\t | ASCII 水平製表(TAB) |
\v | ASCII 垂直製表(VT) |
\ooo | 八進位制的 ooo 的字元。與標準C中一樣,最多可接收3個八進位制數位 |
\xhh | 十六進位制值 hh 的字元。與標準C不同,只需要2個十六進位制數位 |
\N{name} | Unicode 資料庫中名稱為 name 的字元。【提示】:只在字串字面值中識別的跳脫序列 |
\uxxxx | 16 位的十六進位制值為 xxxx 的字元。4個十六進位制數位是必需的。【提示】:只在字串字面值中識別的跳脫序列 |
\Uxxxxxxxx | 32 位的十六進位制值為 xxxxxxxx 的字元,任何 Unicode 字元可以這種方式被編碼。8個十六進位制數位是必需的。【提示】:只在字串字面值中識別的跳脫序列 |
分別使用跳脫字元、八進位制數位、十六進位制數位表示換行符,如下:
str1 = "Hi, \nAmoXiang" # 使用跳脫字元\n表示換行符
str2 = "Hi, \12AmoXiang" # 使用八進位制數位12表示換行符
str3 = "Hi, \x0aAmoXiang" # 使用十六進位制數位 0a 表示換行符
print(str1)
print(str2)
print(str3)
程式執行結果如下圖所示:
如果八進位制數位不滿3位,則首位自動補充0。如果八進位制數位超出3位,十六進位制數位超出2位,超出數位將視為普通字元顯示,如下:
str1 = "Hi, \012AmoXiang" # 使用3位八進位制數位表示換行符,最多允許使用3位八進位制數位
str2 = "Hi, \12Python" # 使用2位八進位制數位表示換行符
str3 = "Hi, \x0a0AmoXiang" # 最多允許使用2位十六進位制數位
print(str1)
print(str2)
print(str3)
程式執行結果如下圖所示:
在 Python3 中,字串常見的有 3 種形式:普通字串(str)、Unicode 字串(unicode) 和原生字串(也稱原義字串)。原生字串的出現目的:解決在字串中顯示特殊字元。在原生字串裡,所有的字元都直接按照字面的意思來使用,不支援跳脫序列和非列印的字元。
原生字串的這個特性讓一些工作變得非常方便。例如,在使用正規表示式的過程中,正規表示式字串,通常是由代表字元、分組、匹配資訊、變數名和字元類等特殊符號組成。當使用特殊字元時,\字元
格式的特殊字元容易被歧義,這時使用原生字串就會派上用場。可以使用 r
或 R
來定義原生字串,這個操作符必須緊靠在第一個引號前面。語法格式如下:
r"原生字串"
R"原生字串"
定義檔案路徑的字串時,會使用很多反斜槓,如果每個反斜槓都用歧義字串來表示會很麻煩,可以採用下面程式碼來表示:
# str1 = "C:\Users\AmoXiang\PycharmProjects" # 直接寫\ 會報錯 \U跳脫
str2 = "C:\\Users\\AmoXiang\\PycharmProjects" # 跳脫字元
str3 = r"C:\Users\AmoXiang\PycharmProjects" # 不跳脫,使用原生字串
# print(str1)
print(str2) # 輸出:C:\Users\AmoXiang\PycharmProjects
print(str3) # 輸出:C:\Users\AmoXiang\PycharmProjects
Unicode 字串
從 Python 1.6 開始支援 Unicode 字串,用來表示雙位元組、多位元組字元、實現與其他字元編碼的格式轉換。在 Python 中,定義 Unicode 字串與定義普通字串一樣簡單,語法格式如下:
u'Unicode 字串'
U"Unicode 字串"
引號前面的操作符 u 或 U 表示建立的是一個 Unicode 字串。如果想加入特殊字元,可以使用 Unicode 編碼。例如:
str1 = u"Hello\u0020World"
print(str1) # 輸出:Hello World
被替換的 \u0020
識別符號表示在給定位置插入編碼值為 0x0020
的 Unicode 字元(空格符)。Unicode 字串的作用:u 操作符後面字串將以 Unicode 格式進行編碼,防止因為原始碼儲存格式問題,導致再次使用時出現亂碼。
unicode() 和 unichr() 函數可以作為 Unicode 版本的 str()和chr()。unicode()函數可以把任何 Python 的資料型別轉換成一個 Unicode 字串,如果物件定義了 __unicode__()
魔術方法,它還可以把該物件轉換成相應的 Unicode 字串。unichr() 函數和chr()函數功能基本一樣,只不過返回 Unicode 的字元。
字元編碼型別
字元編碼就是把字元集中的字元編碼為指定集合中某一物件,以便文字在計算機中儲存和傳遞。常用字元編碼型別如下。
讀者想要詳細瞭解可以點選 編碼百度百科 進行學習。
在 Python 中,有兩種常用的字串型別,分別為 str 和 bytes。其中, str 表示 Unicode 字元(ASCII或者其他),bytes 表示二進位制資料(包括編碼的文字)。這兩種型別的字串不能拼接在一起使用。通常情況下,str 在記憶體中以 Unicode 表示,一個字元對應若干個位元組。但是如果在網路上傳輸,或者存到磁碟上,就需要把 str 轉換為位元組型別,即 bytes 型別。
位元組串(bytes)也稱位元組序列,是不可變的序列,儲存以位元組為單位的資料。提示:bytes 型別是 Python3 新增的一種資料型別。位元組串與字串的比較:
除了操作單元不同外,位元組串與字串的用法基本相同。它們之間的對映被稱為解碼或編碼。定義位元組串的方法如下:
(1) 使用字面值:以 b 操作符為字首的 ASCII 字串。語法格式如下:
b"ASCII 字串"
b"跳脫序列"
位元組是 0~255 之間的整數,而 ASCII 字元集範圍為 0~255,因此它們之間可以直接對映。通過跳脫序列可以對映更大規模的字元集。使用字面值直接定義位元組串,如下:
# 建立空位元組串的字面值
byte1 = b''
byte2 = b""
byte3 = b''''''
byte4 = b""""""
# 建立非空位元組串的字面值
byte5 = b'ABCD'
byte6 = b'\x41\x42'
print(byte1)
print(byte6)
(2) 使用 bytes() 函數:使用 bytes() 函數可以建立一個位元組串物件,簡明語法格式如下:
bytes() # 生成一個空的位元組串,等同於b''
bytes(整型可迭代物件) # 用可迭代物件初始化一個位元組串,元素必須為[0,255]中的整數
bytes(整數n) # 生成n個值為零的位元組串
bytes('字串', encoding='編碼型別') # 使用字串的轉換編碼生成一個位元組串
下面範例使用 bytes()函數建立多個位元組串物件:
a = bytes() # 等效於b''
b = bytes([10, 20, 30, 65, 66, 67]) # 等效於b'\n\x14\xleABC'
print(b)
c = bytes(range(65, 65 + 26))
print(c)
d = bytes(5)
print(d)
e = bytes('hello 中國', 'utf-8')
print(e)
程式執行結果如下:
位元組串是不可變序列,使用 bytearray() 可以建立可變的位元組序列,也稱為位元組陣列(bytearray)。陣列是每個元素型別完全相同的一組列表,因此可以使用操作列表的方法來運算元組。bytearray() 函數的簡明語法格式如下:
bytearray() # 生成一個空的可變位元組串,等同於 bytearray(b'')
bytearray(整型可迭代物件) # 用可迭代物件初始化一個可變位元組串,元素必須為 [0, 255] 中的整數
bytearray(整數n) # 生成 n 個值為零的可變位元組串
bytearray(字串, encoding='utf-8') # 用字串的轉換編碼生成一個可變位元組串
字元編碼和解碼
在編碼轉換時,通常以 Unicode 作為中間碼,即先將一種型別的字串解碼(decode)成 Unicode,再從 Unicode 編碼(encode)成另一種型別的字串。
(1) 使用 encode()
使用字串物件的 encode()方法可以根據引數 encoding 指定的編碼格式將字串編碼為二進位制資料的位元組串,語法格式如下:
str.encode(encoding='UTF-8', errors='strict')
str 表示字串物件:引數 encoding 表示要使用得編碼型別,預設為 UTF-8
,引數 errors 設定不同錯誤的處理方案,預設為 strict
,表示遇到非法字元就會丟擲異常,其他取值包括 ignore
(忽略非法字元)、replace
(用 ?
替換非法字元)、xmlcharrefreplace
(使用 XML 的字元參照)、backslashreplace
,以及通過 codecs.register_error()
註冊的任何值。
【範例1】本例使用 encode()方法對 中文
字串進行編碼。
u = "中文"
str1 = u.encode("gb2312")
print(str1)
str2 = u.encode("gbk")
print(str2)
str3 = u.encode("utf-8")
print(str3)
(2) 使用 decode()
與 encode() 方法操作相反,使用 decode()方法可以解碼字串,即根據引數 encoding 指定的編碼格式將二進位制資料的位元組串解碼為字串。語法格式如下:
str.decode(encoding='UTF-8', errors='strict')
str 表示被 decode()解碼的位元組串,該方法的引數與 encode()方法的引數用法相同。最後返回解碼後的字串。
【範例2】針對範例1,可以使用下面程式碼對編碼字串進行解碼。
u = "中文"
str1 = u.encode("gb2312")
u1 = str1.decode("gb2312")
print(u1) # 輸出:中文
u2 = str1.decode("utf-8") # 報錯,因為str1是gb2312編碼的
"""
報錯如下:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
"""
encode()和decode()方法的引數編碼格式必須一致,否則將丟擲上面程式碼所示的異常。
由於不同的字元所佔位元組數不同,所以要計算字串的長度,需要先了解各字元所佔的位元組數。在 Python 中,數位、英文、小數點、下劃線和空格佔一個位元組;一個漢字可能會佔 2~4 個位元組,佔幾個位元組取決於採用的編碼。漢字在 GBK/GB2312 編碼中佔 2 個位元組,在 UTF-8/unicode 編碼中一般佔用 3個位元組(或4個位元組)。下面以 Python 預設的 UTF-8 編碼為例進行說明,即一個漢字佔 3 個位元組,如下圖所示。
在 Python 中,提供了 len() 函數計算字串的長度,語法格式如下:
len(string)
其中,string 用於指定要進行長度統計的字串。例如,定義一個字串,內容為 人生苦短,我用 Python!
,然後應用 len() 函數計算該字串的長度,程式碼如下:
上面的程式碼在執行後,將輸出結果15。從上面的結果中可以看出,在預設的情況下,通過 len() 函數計算字串的長度時,不區分英文、數位和漢字,所有字元都按一個字元計算。在實際開發時,有時需要獲取字串所佔的實際位元組數,即如果採用 UTF-8 編碼,漢字佔3個位元組,採用 GBK 或者 GB2312 編碼時,漢字佔2個位元組。這時,可以通過使用 encode() 方法進行編碼後再進行獲取。範例程式碼如下:
獲取採用 UTF-8 編碼的字串的長度:因為漢字加中文標點符號共7個,佔 21 個位元組,英文字母和英文的標點符號佔8個位元組,共29個位元組。獲取採用 GBK 編碼的字串的長度:因為漢字加中文標點符號共7個,佔14個位元組,英文字母和英文標點符號佔8個位元組,共22個位元組。
存取字串
Python 不支援單字元型別,單字元在 Python 中也是作為一個字串使用。Python 存取字串中的字元有兩種方式。
(1) 索引存取。索引
又叫 下標
,就是編號。比如火車座位號,座位號的作用:按照編號快速找到對應的座位。同理,索引的作用即是通過索引快速找到對應的資料。
在 Python 中,字串是一種有序序列,字串裡的每一個字元都有一個數位編號標識其在字串中的位置,從左至右依次是:0、1、2、…、n-1,如圖所示:
Python 比較神奇,它的索引可以是負數。這個索引從右向左計數,也就是從最後的一個元素開始計數,從右至左依次是 -1、-2、-3、…、-n(其中 n 是字串的長度)。如圖所示:
通過索引來存取字串中的某個字元。程式碼如下:
str1 = "AmoXiang" # 定義字串
print(str1[2]) # 讀取第3個字元,輸出為o
print(str1[-2]) # 讀取倒數第2個字元,輸出為n
(2) 切片存取。切片操作是存取字串元素的另一種方法,它可以存取一定範圍內的元素。通過切片操作可以生成一個新的字串。字串、列表、元組 都支援切片操作。實現切片操作的語法如下:
sname[start:end:step]
引數說明:
字串切片範例程式碼如下:
str1 = "123456789123456789"
print(str1[0:6]) # 輸出:123456
print(str1[1:20:2]) # 輸出:246813579
str2 = "abcdefghijklmnopqrstuvwxyz"
print(str2[:20]) # 不指定start,則從第1個字元開始,輸出:abcdefghijklmnopqrst
print(str2[20:]) # 不指定end,則直到結尾字元,輸出:uvwxyz
print(str2[:-6]) # 指定end為負數,則從右向左倒數第6個字元
print(str2[:]) # 不指定start和end,相當於print(str2)
print(str2[::3]) # 僅指定步長:adgjmpsvy
print(str2[::-1]) # 逆序(反轉)輸出:zyxwvutsrqponmlkjihgfedcba
print(str2[:19:-1]) # 倒序輸出最後6個字元zyxwvu
print(str2[-10:-19:-1]) # 倒序輸出中間9個字元:qponmlkji
注意:當切片的第3個引數為負數時,表示逆序輸出,即輸出順序為從右到左,而不是從左到右,切片的方向一定要保持一致,例如:str2[1:10:-1] 1:10 表示是從左到右順序,而步長為-1,表示從右到左順序,方向不一致,所以最後切片的結果一定為空。練習:說出下面程式的輸出結果。
name = "abcdefg"
print(name[2:5:1])
print(name[2:5])
print(name[:5])
print(name[1:])
print(name[:])
print(name[::2])
print(name[:-1])
print(name[-4:-1])
print(name[::-1])
print(name[-1:-3:1])
遍歷字串
在字串過濾、篩選和編碼時,經常需要遍歷字串。遍歷字串的方法有多種,具體說明如下。【範例1】使用 for 語句迴圈遍歷字串,然後把每個字元都轉換為大寫形式並輸出:
s1 = "python" # 定義字串
L = [] # 定義臨時備用列表
for i in s1: # 迭代字串
L.append(i.upper()) # 把每個字元轉換為大寫形式
print("".join(L)) # 輸出大寫字串 PYTHON
使用 range() 函數,然後把字串長度作為引數傳入。【範例2】針對範例1,也可以按照以下方式遍歷字串。
s1 = "python" # 定義字串
L = [] # 定義臨時備用列表
for i in range(len(s1)): # 根據字串長度遍歷字串下標數位,
# 從0開始,直到字串長度
L.append(s1[i].upper()) # 把每個字元轉換為大寫形式
print("".join(L)) # 輸出大寫字串 PYTHON
使用 enumerate()。enumerate() 函數將一個可迭代的物件組合為一個索引序列。【範例3】針對範例1,使用 enumerate() 函數將字串轉換為索引序列,然後再迭代操作。
s1 = "python" # 定義字串
L = [] # 定義臨時備用列表
for i, char in enumerate(s1): # 把字串轉換為索引序列,然後再遍歷
L.append(char.upper()) # 把每個字元轉換為大寫形式
print("".join(L)) # 輸出大寫字串 PYTHON
使用 iter()。使用 iter() 函數可以生成迭代器。語法格式如下:
iter(object[, sentinel])
引數 object 表示支援迭代的集合物件,sentinel 是一個可選引數,如果傳遞了第 2 個引數,則引數 object 必須是一個可呼叫的物件(如函數),此時,iter() 函數將建立一個迭代器物件,每次呼叫這個迭代器物件的 __next__()
方法時,都會呼叫 object。【範例4】針對範例1,使用 iter() 函數將字串生成迭代器,然後再遍歷操作。
s1 = "python" # 定義字串
L = [] # 定義臨時備用列表
for item in iter(s1): # 把字串生成迭代器,然後再遍歷
L.append(item.upper()) # 把每個字元轉換為大寫形式
print("".join(L)) # 輸出大寫字串 PYTHON
逆序遍歷。逆序遍歷就是從右到左反向迭代物件。【範例5】本範例演示了 3 種逆序遍歷字串的方法。
s1 = "Python"
print("1. 通過下標逆序遍歷:")
for i in s1[::-1]:
print(i, end="")
print("\n2. 通過下標逆序遍歷:")
for i in range(len(s1) - 1, -1, -1):
print(s1[i], end="")
print("\n3. 通過reversed()逆序遍歷:")
for i in reversed(s1):
print(i, end="")
案例1:判斷兩個字串是否為變形詞
假設給定兩個字串 str1、str2,判斷這兩個字串中出現的字元是否一致,字元數量是否一致,當兩個字串的字元和數量一致時,則稱這兩個字串為變形詞。例如:
str1 = "python", str2="thpyon", 返回True
str2 = "python", str2="thonp", 返回False
範例程式碼如下:
# -*- coding: UTF-8 -*-
"""
@author:AmoXiang
@file:2.判斷兩個字串是否為變形詞.py
@time:2021/01/16
"""
def is_deformation(str1, str2): # 定義變形詞函數
if str1 is None or str2 is None or len(str1) != len(str2): # 當條件不符合時
return False # 返回False
if len(str1) == 0 and len(str2) == 0: # 當兩個字串長度都為0時
return True # 返回True
dic = dict() # 定義一個空字典
for char in str1: # 迴圈遍歷字串str1
if char not in dic: # 判斷字元是否在字典中
dic[char] = 1 # 不存在時,賦值為1
else:
dic[char] = dic[char] + 1 # 存在時字元的值累加
for char in str2: # 迴圈遍歷字串str2
if char not in dic: # 當str2的字元不在字典中時 返回False
return False
else:
dic[char] = dic[char] - 1 # 當str2和str1的字元種類一致時,字典中的字元值自減1
# 字元的值小於0,即字串的字元數量不一致 返回False 否則返回True
if dic[char] < 0:
return False
return True
str1 = "python"
str2 = "thpyon"
str3 = "hello"
str4 = "helo"
# 輸出:python thpyon is deformation: True
print(str1, str2, "is deformation:", is_deformation(str1, str2))
# 輸出:hello helo is deformation: False
print(str3, str4, "is deformation:", is_deformation(str3, str4))
案例2:位元組串的應用之計算md5
在計算 md5 值的過程中,有一步要使用 update 方法,而該方法只接受 bytes 型別資料。
import hashlib
string = "123456"
m = hashlib.md5() # 建立md5物件
str_bytes = string.encode(encoding='utf-8')
print(type(str_bytes)) # <class 'bytes'>
m.update(str_bytes) # update方法只接收bytes型別資料作為引數
str_md5 = m.hexdigest() # 得到雜湊後的字串
print('MD5雜湊前為 :' + string) # MD5雜湊前為 :123456
print('MD5雜湊後為 :' + str_md5) # MD5雜湊後為 :e10adc3949ba59abbe56e057f20f883e
案例3:二進位制讀寫檔案。
使用二進位制方式讀寫檔案時,均要用到 bytes 型別,二進位制寫檔案時,write()方法只接受 bytes 型別資料,因此需要先將字串轉成 bytes 型別資料;讀取二進位制檔案時,read()方法返回的是 bytes 型別資料,使用 decode()方法可將 bytes 型別轉成字串。
f = open('data.txt', 'wb')
text = '二進位制寫檔案'
text_bytes = text.encode('utf-8')
f.write(text_bytes)
f.close()
f = open('data.txt', 'rb')
data = f.read()
print(data, type(data))
str_data = data.decode('utf-8')
print(str_data)
f.close()
在 Python 的開發過程中,為了實現某項功能,經常需要對某些字串進行特殊處理,如拼接字串、擷取字串、格式化字串等。下面將對 Python 中常用的字串操作方法進行介紹。
連線字串就是將不同的字串直接或者通過指定的分隔符組合到一起變成一個字串。在 Python 中,主要有兩種方法:拼接和合並,下面分別進行介紹。使用 +
運運算元可以完成對多個字串的拼接,+
運運算元可以連線多個字串併產生一個字串物件。例如,定義兩個字串:一個用於儲存英文版的名言;另一個用於儲存中文版的名言,然後使用 +
運運算元連線,程式碼如下:
mot_en = "Remembrance is a form of meeting. Forgetfulness is a form of freedom."
mot_cn = "記憶是一種相遇。遺忘是一種自由。"
print(mot_en + "-" + mot_cn)
字串不允許直接與其他型別的資料拼接,例如,使用下面的程式碼將字串與數值拼接在一起,將產生下圖所示的異常:
在解決該問題時,可以將整數轉換為字串,然後以拼接字串的方式輸出該內容。將整數轉換為字串,可以使用 str() 函數,修改後的程式碼如下:
str1 = "今年我剛滿" # 定義字串
age = 18 # 定義一個整數
str2 = "歲" # 定義字串
print(str1 + str(age) + str2)
如果想要將一個字串複製多次,則可以使用乘法實現。例如,將一個字串 「Amo 很酷!」 複製5次並輸出,程式碼如下:
合併字串與拼接字串不同,它會將多個字串採用固定的分隔符連線在一起。例如,字串 Amo*Paul*Jason*Ben
,就可以看作是通過分隔符 *
將 [「Amo」, "Paul’, 「Jason」, 「Ben」] 列表合併為一個字串的結果。合併字串可以使用字串物件的 join() 方法實現,語法如下:
str_new = string.join(iterable)
引數說明:
範例程式碼如下:
list_friend = ["Amo", "Paul", "Jason", "Ben"] # 好友列表
str_friend = " @".join(list_friend) # 用空格+@符號進行連線
at = "@" + str_friend
print(f"您要@的好友:{at}")
程式執行結果如下圖所示:
其他範例如下:
補充:在 Python 中,只要把兩個字串放在一起,中間有空白或者沒有空白,兩個字串將自動連線為一個字串。範例如下:
上述方法只能用在字串字面值之間,不能夠用在字串變數之間。在 print() 函數中,如果兩個字串被逗號分隔,那麼這兩個字串將被連續輸出,但是字串之間會多出一個空格。例如:
上述方法僅能用在 print() 函數內,如果用在其他場合,將被視為元組物件。
(1) count():count() 方法用於統計字串裡某個子字串出現的次數。如果檢索的子字串不存在,則返回0;否則返回出現的次數,語法格式如下:
str.count(sub, start=0, end=len(string))
str 表示字串。引數 sub 表示要檢索的子字串;start 表示字串開始統計的位置,預設為第 1 個字元(索引值為 0);end 表示字串中結束統計的位置,預設為字串的最後一個位置。範例程式碼如下:
(2) find() 方法:該方法用於檢索是否包含指定的子字串。如果檢索的字串不存在,則返回 -1;否則返回首次出現該子字串時的索引。語法如下:
str.find(sub, start=0, end=len(string))
str 表示原字串。引數 sub 表示要檢索的子字串。start 可選引數,表示檢索範圍的起始位置的索引,如果不指定,則從頭開始檢索。end 可選引數,表示檢索範圍的結束位置的索引,如果不指定,則一直檢索到結尾。使用 find() 方法檢索 長
在字串中的索引位置。範例程式碼如下:
my_str = "海水朝朝朝朝朝朝朝落,浮雲長長長長長長長消"
sub = "長" # 要檢索的字串
print(my_str.find(sub)) # 在整個字串中檢索,輸出:13
print(my_str.find(sub, 14)) # 從下標14位元置開始檢索,輸出為:14
print(my_str.find(sub, 10, 13)) # 從下標10~13 範圍開始檢索,輸出為-1,沒有找到
檢索範圍包含起始點位置,但不包含中止點位置。Python 中的字串物件還提供了 rfind() 方法,其作用與 find() 方法類似,只是從字串的右邊開始查詢。把上面的 find() 方法改為 rfind() 方法,如下:
my_str = "海水朝朝朝朝朝朝朝落,浮雲長長長長長長長消"
sub = "長" # 要檢索的字串
print(my_str.rfind(sub)) # 在整個字串中檢索,輸出:19
print(my_str.rfind(sub, 14)) # 從下標14位元置開始檢索,輸出為:19
print(my_str.rfind(sub, 10, 13)) # 從下標10~13 範圍開始檢索,輸出為-1,沒有找到
(3) index() 方法:index() 方法同 find() 方法類似,也是用於檢索是否包含指定的子字串。只不過如果使用 index() 方法,當指定的字串不存在時會顯示異常。語法如下:
str.index(sub, start=0, end=len(string))
str 表示原字串。引數 sub 表示要檢索的子字串。start 可選引數,表示檢索範圍的起始位置的索引,如果不指定,則從頭開始檢索。end 可選引數,表示檢索範圍的結束位置的索引,如果不指定,則一直檢索到結尾。使用 index() 方法檢索 長
在字串中的索引位置。範例程式碼如下:
my_str = "海水朝朝朝朝朝朝朝落,浮雲長長長長長長長消"
sub = "長" # 要檢索的字串
print(my_str.index(sub)) # 在整個字串中檢索,輸出:13
print(my_str.index(sub, 14)) # 從下標14位元置開始檢索,輸出為:14
print(my_str.index(sub, 10, 13)) # 從下標10~13 範圍開始檢索,沒有找到,丟擲異常 ValueError
程式執行結果如下圖所示:
Python 的字串物件還提供了 rindex() 方法,其作用與 index() 方法類似,只是要從右邊開始查詢。總結:index() 方法和 find() 方法的功能和用法相同。rindex() 與 rfind() 方法的功能和用法相同。唯一區別是:當 index() 和 rindex() 方法搜尋不到子字串時,將丟擲 ValueError 錯誤。
(1) replace() 方法:replace() 方法用於將一個字串的子字串替換為另一個字串,並且返回被替換後的字串。如果未找到要替換的字串,則返回原字串。語法如下:
str.replace(old, new, count)
str 表示原字串。old 表示要替換的字串。new 表示替換後的字串。count 可選引數,表示替換次數,如果不指定,則全部替換。範例程式碼如下:
my_str = "hello world and amoxiang and amo and Python"
print(my_str)
# 結果:hello world And amoxiang And amo And Python
print(my_str.replace('and', 'And'))
# 結果:hello world And amoxiang And amo and Python
print(my_str.replace('and', 'And', 2))
print(my_str.replace('and', 'And', 10))
程式執行結果如下圖所示:
注意:資料按照是否能直接修改分為 可變型別 和 不可變型別 兩種。字串型別的資料修改的時候不能改變原有字串,屬於不能直接修改資料的型別即是不可變型別。
(2) expandtabs() 方法:把字串中的 Tab 符號( \t
) 轉為空格,Tab (\t
) 符號預設的空格數是8,語法格式如下:
str1.expandtabs(tabsize=8)
引數 tabsize 指定轉換字串中的 Tab 符號轉為空格的字元數,預設值為8。使用方法如下:
expandtabs(8) 不是將 \t
直接替換為8個空格,而是根據 Tab 字元前面的字元數確定替換寬度。範例程式碼如下:
print(len("1\t".expandtabs(8))) # 輸出為8,新增7個空格
print(len("12\t".expandtabs(8))) # 輸出為8,新增6個空格
print(len("123\t".expandtabs(8))) # 輸出為8,新增5個空格
print(len("1\t1".expandtabs(8))) # 輸出為9,新增7個空格
print(len("12\t12".expandtabs(8))) # 輸出為10,新增6個空格
print(len("123\t123".expandtabs(8))) # 輸出為11,新增5個空格
print(len("123456781\t".expandtabs(8))) # 輸出為16,新增7個空格
print(len("1234567812345678\t".expandtabs(8))) # 輸出為24,新增8個空格
結果分析:使用 \t
前面字元的個數對 8 取餘數,新增空格的數量 = 8 - 餘數。
(3) translate() 和 maketrans() 方法:translate() 方法能夠根據參數列翻譯字串中的字元。語法格式如下:
str.translate(table)
bytes.translate(table[, delete])
bytearray.translate(table[, delete])
str 表示字串物件;bytes 表示位元組串;bytearray 表示位元組陣列。引數 table 表示翻譯表,翻譯表通過 maketrans() 方法生成。translate() 方法返回翻譯後的字串,如果設定了 delete 引數,則將原來 bytes 中屬於 delete 的字元刪除,剩下的字元根據引數 table 進行對映。maketrans() 方法用於建立字元對映的轉換表。語法格式如下:
str.maketrans(intab, outtab[, delchars])
bytes.maketrans(intab, outtab)
bytearray.maketrans(intab, outtab)
第1個引數是字串,表示需要轉換的字元。第2個引數也是字串,表示要轉換的目標,兩個字串的長度必須相同,為一一對應的關係。第3個引數為可選引數,表示要刪除的字元組成的字串。
【範例1】使用 str.maketrans() 方法生成一個大小寫字母對映表,然後把字串全部轉換為小寫。
a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 大寫字元集
b = "abcdefghijklmnopqrstuvwxyz" # 小寫字元集
table = str.maketrans(a, b) # 建立對映表
s = "PYTHON"
print(s.translate(table)) # 輸出:python
【範例2】針對範例1,可以設定要刪除的字元,如 THON。
a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 大寫字元集
b = "abcdefghijklmnopqrstuvwxyz" # 小寫字元集
de = "THON" # 刪除字元集
t1 = str.maketrans(a, b) # 建立字元對映轉換表
t2 = str.maketrans(a, b, de) # 建立字元對映轉換表,並刪除指定字元
s = "PYTHON" # 原始字串
print(s.translate(t1)) # 輸出:python
print(s.translate(t2)) # 輸出:py
【範例3】可以把普通字串轉換為位元組串,然後使用 translate() 方法先刪除再轉換。
a = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 大寫位元組型字元集
b = b"abcdefghijklmnopqrstuvwxyz" # 小寫位元組型字元集
de = b"THON" # 刪除位元組型字元集
t1 = bytes.maketrans(a, b) # 建立位元組型字元對映轉換表
s = b"PYTHON" # 原始位元組串
s = s.translate(None, de) # 若table引數為None,則只刪除不對映
s = s.translate(t1) # 執行對映轉換
print(s) # 輸出:b'py'
(1) split() 方法:字串物件的 split() 方法可以實現字串分割,也就是把一個字串按照指定的分隔符切分為字串列表。在該列表的元素中,不包括分隔符。split() 方法的語法如下:
str.split(sep,maxsplit)
str 表示要進行分割的字串。sep 用於指定分隔符,可以包含多個字元,預設為 None,即所有的空字元(包括空格、換行 \n
、製表符 \t
等)。maxsplit 可選引數,用於指定分割的次數,如果不指定或者為 -1,則分割次數沒有限制,否則返回結果列表的元素個數最多為 maxsplit+1。方法返回值:分隔後的字串列表。該列表的元素為以每個分隔符為界限進行分割後的字串(不包括分隔符),當該分割符前面(或者與前一個分隔符之間)沒有內容時,將返回一個空字串元素。在 split() 方法中,如果不指定 sep 引數,那麼也不能指定 maxsplit 引數。範例程式碼如下:
拓展1:演示 splitlines() 方法的基本使用。
str1 = "a\n\nb\rc\r\nd"
t1 = str1.splitlines() # 不包含換行符
t2 = str1.splitlines(True) # 包含換行符
print(t1) # 輸出:['a', '', 'b', 'c', 'd']
print(t2) # 輸出:['a\n', '\n', 'b\r', 'c\r\n', 'd']
splitlines() 方法實際上就是 split() 方法的特殊應用。即以行(\r
、\r\n
、\n
) 為分隔符來分割字串,返回一個包含各行字串作為元素的列表。語法格式:
str.splitlines([keepends])
引數 keepends 預設為 False,如果為 False,則每行元素中不包含行識別符號;如果為 True,則元素中保留識別符號。
拓展2:使用 partition() 和 rpartition() 方法。使用 partition() 方法可以根據指定的分隔符將字串進行分割。語法格式如下:
str.partition(sep)
引數 sep 表示分隔的子字串(分隔符)。如果字串中包含指定的分隔符,則返回一個包含3個元素的元組。第1個元素為分隔符左邊的子字串。第2個元素為分隔符本身,第3個元素為分隔符右邊的子字串。範例程式碼如下:
str1 = "https://blog.csdn.net/xw1680"
print(str1.partition(".")) # 輸出:('https://blog', '.', 'csdn.net/xw1680')
print(str1.rpartition(".")) # 輸出:('https://blog.csdn', '.', 'net/xw1680')
print(str1.partition("|")) # 輸出:('https://blog.csdn.net/xw1680', '', '')
rpartition() 方法類似於 partition() 方法,只是該方法是從目標字串的右邊開始搜尋分隔符。
(1) capitalize() 方法:將字串的第一個字母變成大寫,其他字母變成小寫。語法格式如下:
str.capitalize()
該方法沒有引數,返回值為生成的新字串。例如:
str1 = "I Love Amo" # 定義字串
print(str1.capitalize()) # 輸出:I love amo
(2) title() 方法:返回標題化的字串,即字串中每個單詞首字母大寫,其餘字母均為小寫。語法格式如下:
str.title()
該方法沒有引數,返回值為生成的新字串。例如:
str1 = "i love amo" # 定義字串
print(str1.title()) # 輸出:I Love Amo
(3) 在 Python 中,字串物件提供了 lower() 方法和 upper() 方法進行字母的大小寫轉換,即可用於將大寫字母轉換為小寫字母,或者將小寫字母轉換為大寫字母,示意如下圖所示。
lower() 方法用於將字串中的大寫字母轉換為小寫字母。如果字串中沒有需要被轉換的字元,則將原字串返回;否則將返回一個新的字串,將原字串中每個需要進行小寫轉換的字母都轉換成等價的小寫字母。字元長度與原字元長度相同。lower() 方法的語法如下:
str.lower() # str 為要進行轉換的字串
upper() 方法用於將字串中的小寫字母轉換為大寫字母。如果字串中沒有需要被轉換的字元,則將原字串返回;否則返回一個新字串,將原字串中每個需要進行大寫轉換的字母都轉換成等價的大寫字母。新字元的長度與原字元的長度相同。upper() 方法的語法如下:
str.upper() # str 為要進行轉換的字串
兩個方法都沒有引數,lower() 方法返回為小寫後生成的字串。upper() 方法為大寫後生成的字串。範例程式碼如下:
(4) swapcase() 方法:將字串的大小寫字母進行轉換。語法格式如下:
str.swapcase()
該方法沒有引數,返回大小寫字母轉換後生成新的字串。例如:
str1 = "I Love Amo" # 定義字串
print(str1.swapcase()) # 輸出:i lOVE aMO
去除字串中的空格和特殊字元。使用者在輸入資料時,可能會無意中輸入多餘的空格;或在一些情況下,字串前後不允許出現空格和特殊字元,此時就需要去除字串中的空格和特殊字元。例如,下圖中 HELLO
這個字串的前後都有一個空格。可以使用 Python 中的字串提供的 strip() 方法去除字串左右兩邊的空格和特殊字元;也可以使用字串的 lstrip() 方法去除字串左邊的空格和特殊字元,再使用字串的 rstrip() 方法去除字串中右邊的空格和特殊字元。
這裡的特殊字元是指製表符 \t
、回車符\r
、換行符\n
等。
(1) strip() 方法用於去掉字串左、右兩側的空格和特殊字元。語法格式如下:
str.strip([chars])
str 為要去除空格和特殊字元的字串。chars 為可選引數,用於指定要去除的字元,可以指定多個。如果設定chars為 @.
則去除左、右兩側包括的 @
或 .
;如果不指定 chars 引數,預設將去除空格、製表符\t
、回車符\r
、換行符\n
等。範例程式碼如下:
str1 = "https://blog.csdn.net/xw1680?\t\n\r"
print(f"原字串str1: {str1}。")
print(f"字串 : {str1.strip()}。")
str2 = "@廈門大學.@."
print(f"原字串str2: {str2}。")
print(f"字串 : {str2.strip('@.')}。")
程式執行結果如下圖所示:
(2) lstrip() 方法用於去掉字串左側的空格和特殊字元。語法格式如下:
str.lstrip([chars])
str 為要去除空格和特殊字元的字串。chars 為可選引數,用於指定要去除的字元,可以指定多個。如果設定chars為 @.
則去除左、右兩側包括的 @
或 .
;如果不指定 chars 引數,預設將去除空格、製表符\t
、回車符\r
、換行符\n
等。範例程式碼如下:
(3) rstrip() 方法用於去掉字串右側的空格和特殊字元,語法格式如下:
str.rstrip([chars])
str 為要去除空格和特殊字元的字串。chars 為可選引數,用於指定要去除的字元,可以指定多個。如果設定chars為 @.
則去除左、右兩側包括的 @
或 .
;如果不指定 chars 引數,預設將去除空格、製表符\t
、回車符\r
、換行符\n
等。範例程式碼如下:
總結:無論是 strip() 方法,還是 lstrip() 和 rstrip() 方法,可以清除指定的字串,字串可以是一個字元或者多個字元,匹配時不是按照整體進行匹配,而是逐個進行匹配。
(1) center() 方法:使用 center() 方法可以設定字串居中顯示。語法格式如下:
str.center(width[, fillchar])
str 表示字串物件。引數 width 表示字串的總寬度,單位為字元;fillchar 表示填充字元,預設值為空格。center() 方法將根據 width 設定的寬度居中,然後使用 fillchar 引數填充空餘區域,預設填充字元為空格。
【範例1】設定一個總寬度為20的字串,然後定義子字串 Python 居中顯示,剩餘空間填充為下劃線。
(2) ljust() 和 rjust():ljust() 方法能夠返回一個原字串左對齊,並使用指定字元填充至指定長度的新字串。rjust() 方法與 ljust() 方法操作相反,它返回一個原字串右對齊,並使用指定字元填充至指定長度的新字串。語法格式如下:
str.ljust(width[, fillchar])
str.rjust(width[, fillchar])
引數說明與 center() 相同。同樣,如果指定的長度小於原字串的長度,則返回原字串。
【範例2】針對範例1,分別使用 ljust()和rjust() 方法設定字串左對齊和右對齊顯示,同時定義字串總寬度為20個字元。
(3) zfill() 方法:zfill() 方法實際上是 rjust() 方法的特殊用法,它能夠返回指定長度的字串,原字串右對齊,前面填充引數0。語法格式如下:
str.zfill(width)
引數 width 指定字串的長度。
【範例3】設計隨機生成一個 1~999 之間的整數,為了整齊顯示亂數,本範例使用 zfill() 設定亂數總長度為3。
(1) endswith() 方法:用於判斷字串是否以指定的字串結尾,如果以指定字尾結尾,則返回 True;否則返回 False,語法格式如下:
str.endswith(suffix[, start=0[, end=len(str)]])
str 表示字串物件。引數 suffix 可以是一個字串或者一個元素;start 表示檢索字串中的開始位置,預設值為 0;end 表示檢索字元中的結束位置,預設值為字串的長度。
startswith() 方法用於判斷字串是否以指定的字串開頭,用法與 endswith() 方法相同。
str.startswith(suffix[, start=0[, end=len(str)]])
(2) 其他方法說明如下:
檢測字串是否為小寫、大寫或者首字母大寫格式:
方法名 | 功能 |
---|---|
islower() | 檢測字串是否為純小寫的格式。例如:「python」.islower()、「PYTHON」.islower() |
isupper() | 檢測字串是否為純大寫的格式。 |
istitle() | 檢測字串是否為標題化的格式。 |
範例程式碼如下:
str1 = "PYTHON"
str2 = "python"
print(str1.islower()) # False
print(str2.islower()) # True
print(str1.isupper()) # True
print(str2.isupper()) # False
print("Python".isupper()) # False
str3 = "i love python" # 定義字串
str4 = str3.title()
print(str3.istitle()) # False
print(str4.istitle()) # True
拓展:Python 沒有提供 iscapitalize() 方法,用來檢測字串首字母是否為大寫格式。下面自定義 iscapitalize() 函數來完善字串大小寫格式。
# 檢測函數 與capitalize()對應
def iscapitalize(s):
if len(s.strip()) > 0 and not s.isdigit(): # 非空或非數位字串,則進一步檢測
# 使用 capitalize()把字串轉換為首字母大寫形式,然後比較,如果相等,則返回True,否則返回False
return s == s.capitalize()
else:
return False # 如果為空,或者數位,則直接返回False
print(iscapitalize("Python")) # True
print(iscapitalize(" ")) # False
print(iscapitalize("123")) # False
print(iscapitalize("python")) # False
print(iscapitalize("I Love Python")) # False
print(iscapitalize("Python 3.8.6")) # True
數位和字母檢測
方法名 | 功能 |
---|---|
isdigit() | 如果字串只包含數位,則返回 True;否則返回 False。 |
isdecimal() | 如果字串只包含十進位制數位,則返回 True;否則返回 False。 |
isnumeric() | 如果字串中只包含數位字元,則返回 True;否則返回 False。 |
isalpha() | 如果字串中至少有一個字元,並且所有字元都是字母,則返回 True;否則返回 False。 |
isalnum() | 如果字串中至少有一個字元,並且所有字元都是字母或者數位,則返回 True;否則返回 False。 |
範例程式碼如下:
n1 = "1" # Unicode數位
print(n1.isdigit()) # True
print(n1.isdecimal()) # True
print(n1.isnumeric()) # True
n2 = "1" # 全形數位(雙位元組)
print(n2.isdigit()) # True
print(n2.isdecimal()) # True
print(n2.isnumeric()) # True
n3 = b"1" # byte數位(單位元組)
print(n3.isdigit()) # True
# print(n3.isdecimal()) # 報錯:AttributeError: 'bytes' object has no attribute 'isdecimal'
# print(n3.isnumeric()) # 報錯:AttributeError: 'bytes' object has no attribute 'isnumeric'
n4 = "IV" # 羅馬數位
print(n4.isdigit()) # False
print(n4.isdecimal()) # False
print(n4.isnumeric()) # False
n5 = "四" # 漢字數位
print(n5.isdigit()) # False
print(n5.isdecimal()) # False
print(n5.isnumeric()) # True
特殊字元檢測
特殊字元包括空白(空格、製表符、換行符)、可列印字元(製表符、換行符不是,而空格是),以及是否滿足識別符號定義規則。具體說明如下:
方法名 | 功能 |
---|---|
isspace() | 如果字串中只包含空白,則返回 True;否則返回 False。 |
isprintable() | 如果字串中的所有字元都是可列印的字元,或者字串為空,則返回 True;否則返回 False。 可列印字元(製表符、換行符不是,而空格是)。 |
isidentifier() | 如果字串是有效的 Python 識別符號,則返回 True;否則返回 False。 |
範例程式碼如下:
3.1 說出下面切片擷取字串的結果
str1 = "0123456789"
print(str1[0:3])
print(str1[:])
print(str1[6:])
print(str1[:-3])
print(str1[2])
print(str1[-1])
print(str1[::-1])
print(str1[-3:-1])
print(str1[-3:])
print(str1[:-5:-3])
3.2 案例:模擬上傳圖片檔案
通常在上傳檔案的時候對檔案的格式有要求,如上傳圖片的檔案時,格式可以為 .png/.jpg/.gif 等
,只有符合該格式的檔案才可以上傳,通過對字串操作,模擬上傳圖片檔案,演示效果如下圖所示: