天天看點

8. 字元串詳解

作者:茶桁

Hi, 大家好。我是茶桁。

前幾節課中我們學習了函數,那麼這節課開始,我們花幾節課返過頭來詳細的學習一下Python内的資料類型。第一節課,讓我們先從字元串開始:

8. 字元串詳解
  • 回顧字元串的定義方式
  • 了解轉義字元
  • 字元串格式化的方法
  • 字元串相關函數

字元串的定義方式

  1. 單引号定義字元串 ‘ ’
  2. 雙引号定義字元串“ ”
  3. 三引号定義字元串‘’‘内容’‘’或者“”“内容”“”
  4. 字元串定義時,引号可以互相嵌套

轉義字元

一個普通的字元出現在轉義符\的後面時,實作了另外一種意義。
  • \ 轉義符,續行符。

作為轉義符時,在\後面出現的字元可能會實作另外一種意義。

作為續行符時,在行尾使用了\後,可以換行繼續書寫内容。

str = '123'\
    '456'
print(str)

---
123456           

列印結果看,并未換行,說明續行符起作用了。

  • \n 代表一個換行符
str = "歲月是一把殺豬刀, \n但是它拿長得醜的人一點辦法都沒有。"
print(str)

---
歲月是一把殺豬刀, 
但是它拿長得醜的人一點辦法都沒有。           
  • \r代表光标位置(從\r出現的位置開始作為光标的起點)
str = "歲月是一把殺豬刀, \r但是它拿長得醜的人一點辦法都沒有。"
print(str)

---
但是它拿長得醜的人一點辦法都沒有。           
  • \t代表一個水準制表符(table 縮進)
str = "歲月是一把殺豬刀\t但是它拿長得醜的人一點辦法都沒有。"
print(str)

---
歲月是一把殺豬刀    但是它拿長得醜的人一點辦法都沒有。           
  • \b 代表一個倒退符
str = "歲月是一把殺豬刀\b但是它拿長得醜的人一點辦法都沒有。"
print(str)

---
歲月是一把殺豬但是它拿長得醜的人一點辦法都沒有。           

注意看,并不是毫無改變的列印出來了,整句話中\b前面的刀這個字被倒退了。

  • \\ 反轉義\,輸出了\,取消\的轉義效果
str = "歲月是一把殺豬刀\\n但是它拿長得醜的人一點辦法都沒有。"
print(str)

---
歲月是一把殺豬刀\n但是它拿長得醜的人一點辦法都沒有。           

第二個\被前面的\轉義了,是以n就不會再被轉義,也就沒有換行。

  • r, 如果我們想把轉義字元也作為普通字元輸出,那我們可以在字元串的最前面加上r
str = r"歲月是一把殺豬刀\n但是它拿長得醜的人一點辦法都沒有。"
print(str)

---
歲月是一把殺豬刀\n但是它拿長得醜的人一點辦法都沒有。           

字元串内的轉移字元\n被列印了出來。

字元串相關的操作

  • 字元串+操作, 将參與運算的字元串相加後組成一個新的字元串。
str="君不見,黃河之水天上來,奔流到海不複回。"
str2 = "君不見,高堂明鏡悲白發,朝如青絲暮成雪。"
res = '将進酒\n'+ str + '\n' + str2
print(res)

---
将進酒
君不見,黃河之水天上來,奔流到海不複回。
君不見,高堂明鏡悲白發,朝如青絲暮成雪。           
  • 字元串*操作,str*n就是 将目前字元串重複n遍
str = '重要的話說三遍\n' * 3
print(str)

---
重要的話說三遍
重要的話說三遍
重要的話說三遍           
  • 字元串[]切片操作

字元串的索引操作,字元串中隻能使用[]下标通路,不能修改。

str[start:stop:step]
功能,擷取str的特定下标或者對str進行切片操作
參數:
    start: 可選,開始值,預設為0
  stop: 可選,結束值,預設為len(str)
  step:可選,步進值,預設為1           

因為所有參數都是可選項,是以其實我們可以什麼參數都不給,直接使用預設值:

str = '凡詩之所謂風者,多出于裡巷歌謠之作,所謂男女相與詠歌,各言其情者也。'
print(str)
# 等同于
print(str[::])

---
凡詩之所謂風者,多出于裡巷歌謠之作,所謂男女相與詠歌,各言其情者也。
凡詩之所謂風者,多出于裡巷歌謠之作,所謂男女相與詠歌,各言其情者也。           

當我們寫一個值,那就是擷取指定下标的元素:

print(str[6])

---
者           

但是當我們隻寫一個值,并且後面跟上符号::, 那含義就是從start開始,向後取完:

print(str[6::])

---
者,多出于裡巷歌謠之作,所謂男女相與詠歌,各言其情者也。           

從這我們可以看出來,當我們隻寫一個單獨的值而沒有加::的時候,含義就是從start開始,但是并不向後繼續取值,而有了::就是繼續向後取值。其實,隻寫一個:也是一樣的,因為隻要知道向後取值,step預設值就是為1:

print(str[6:])

---
者,多出于裡巷歌謠之作,所謂男女相與詠歌,各言其情者也。           

那如果我們在這個基礎上加上一個值,那就是從start開始直到stop之前。和range()一樣,取不到stop。

print(str[2:6])

---
之所謂風           

然後再多加一個值,和range()一樣,就是往後數step個數再取值:

print(str[2:15:2])

---
之謂者多于巷謠           

其實,這裡比較饒的并不是如何取值,二是::這兩個符号。當我們将上面講的這些内容了解通透後,就可以玩轉字元串的切片了。

那對應的,如果我們想将字元串完全取值,但是是隔一個取一個,那我們就可以使用start和stop的預設值,而隻定義step

print(str[::2])

---
凡之謂者多于巷謠作所男相詠,言情也           

那如果我們想讓整個字元串倒過來呢?

print(str[::-1])

---
。也者情其言各,歌詠與相女男謂所,作之謠歌巷裡于出多,者風謂所之詩凡           

字元串的格式化方法

常用的字元串的格式化方法就是format()

先讓我們看看最普通的方式:

s = '茶桁'
str = '乘舟将欲行,忽聞岸上踏歌聲。'           

我定義了這兩個字元串,現在我想将兩段字元串合在一起變成一句“茶桁乘舟将欲行,忽聞岸上踏歌聲。”(嗯,權吾乃青蓮居士。)

很多小夥伴是不是覺得太簡單了,我們之前學了+号,直接拼接不就好了。自然也是可以的,隻是我們現在要用更普遍和便捷的方式來完成:

s = '茶桁'
str = '{}乘舟将欲行,忽聞岸上踏歌聲。'.format(s)
print(str)

---
茶桁乘舟将欲行,忽聞岸上踏歌聲。           

假如說,我們現在隻有詩詞的大半句,其中少了踏歌行這三個字,那我們又該如何?那我們就往format中傳入兩個參數,後面那個參數自定義出這三個字元就可以了:

s = '茶桁'
str = '{}乘舟将欲行,忽聞岸上{}。'.format(s, "踏歌行")
print(str)

---
茶桁乘舟将欲行,忽聞岸上踏歌行。           

看到這裡,我們是不是認為字元串使用format就隻能順序傳值?第一個答案填入第一個空,第二個答案填入第二個空... 其實不隻是如此,字元串後使用format,其中的{}還可以接受索引傳參:

s = '茶桁'
str = '{1}乘舟将欲行,忽聞岸上{0}。'.format("踏歌行", s)
print(str)

---
茶桁乘舟将欲行,忽聞岸上踏歌行。           

通過索引傳參的适用範圍畢竟還是有限,我們很容易一不小心就會把參數順序搞亂。那還有沒有其他辦法呢?

我們還可以通過關鍵字傳參:

str = '{s2}乘舟将欲行,忽聞岸上{s1}。'.format(s1 = "踏歌行", s2 = "茶桁")
print(str)

---
茶桁乘舟将欲行,忽聞岸上踏歌行。           

那假如說我們得到的是一個清單資料,是否需要先轉換資料?其實也沒必要,format支援對容器型資料的傳參數:

str = '豪放派:{0[0]},婉約派:{0[1]},流氓派:{0[3]},蛋黃派:{0[2]}'.format(['李白','辛棄疾','達利園','茶桁'])
print(str)

---
豪放派:李白,婉約派:辛棄疾,流氓派:茶桁,蛋黃派:達利園           

那麼如果是字典類型的呢?那就更簡單了,我們之前提到的關鍵字傳參,不就正好對應字典嗎?

dict = {'a':'茶桁', 'b':'蛋黃派'}
str = '{a}乘舟将欲行,忽聞岸上{b}'.format(**dict)
print(str)

---
茶桁乘舟将欲行,忽聞岸上蛋黃派           

嗯,不錯。似乎我們建立了一句新的詩句。

其實,format還有其他的用法,就是直接用關鍵字f, 比如:

str = f'{dict["a"]}乘舟将欲行,忽聞岸上{dict["b"]}'
print(str)

---
茶桁乘舟将欲行,忽聞岸上蛋黃派           

f是在3.7版本中新增的格式化方法,在使用的過程中,要注意字元串符号“”和‘’的嵌套關系。

在基本使用之外,我們還有一些風騷的特殊用法,比如,我們可以用format直接限定小數的位數:

str = '圓周率是多少:{:.5f}'.format(3.1415926)
print(str)

---
圓周率是多少:3.14159           

字元串相關函數

在Python中,字元串應該是最常見的資料類型,對應字元串的函數也有不少。大家可以去看看官方的文檔

英文字元與字元檢測相關函數

我們可以傳回字元串的副本,并且将首字母大寫,其餘小寫:

str = 'I am a data product manager'
str.capitalize()

---
'I am a data product manager'           
因為我在使用Jupyter Notebook,是以即便我麼有使用print,依然可以列印出執行結果。隻是僅可以列印最後一個執行的函數。

可以把字元串中的一個單詞的首字母大寫:

str.title()

---
'I Am A Data Product Manager'           

可以全部改為大寫:

str.upper()

---
'I AM A DATA PRODUCT MANAGER'           

把字元串全部改為小寫

str.lower()

---
'i am a data product manager'           

字元串中的大小寫字元轉換,大寫轉小寫,小寫轉大寫:

str.swapcase()

---
'i AM A DATA PRODUCT MANAGER'           

檢測字元是否包含在字元串内:

print('o' in 'love')

---
True           

檢測字元串是否為全部大寫字母組成

str.isupper()

---
False           

檢測字元串是否為全部小寫字母組成

str.islower()

---
False           

檢測字元串是否符合标題title的要求

str.istitle()

---
False           

檢測字元串是否由數字和字母組成,如果字元串中包含來非數字字母的其它字元,則傳回False

str.isalnum()

---
False           

檢測字元串是否全部由字元(包含英文字元和中文)組成

str.isalpha()

---
False           

檢測字元串是否由純數字字元組成

'123'.isdigit()

---
True           

檢測目前字元串是否為 空格 字元組成 ' ’

' '.isspace()

---
True           

檢測字元串是否以指定的字元開始的,也可以指定開始和結束的位置

str.startswith('I')

---
True           
str.startswith('a', 5)

---
True           

檢測字元串是否以 指定的字元 結束的,也可以指定開始和結束的位置

print(str.endswith('a'))
print(str.endswith('a', 5, 11))
print(str.endswith('a', 1, 6))

---
False
True
True           

字元串的查找和操作相關函數(✨ 重點)

前面鋪墊了那麼多之後,接下來這部分,才是這一節的重點。

讓我們先從查找來看:

str.find(sub[, start[, end]])

find會傳回一個子字元串,找到字元中符合條件的第一個字元出現的索引位置,未找到則傳回-1

str = "I am a data product manager."
print(str.find('am'))

---
2           

讓我們用切片的方式反過來找一下看看:

res = str.find('am')
str[res:res+2]

---
'am'           

我們從之前可以知道res取值為2,現在等于是str[2:4], 正好是am所在的位置。

find中有start和end,是支援切片查找的:

print(str.find('am', 0, 4))
print(str.find('am', 4, 10))

---
2
-1           

可以看到,在從4開始找到10的時候找不到am, find有一個功能相同,但是方向不同的方法rfind(), 和find的不同點隻是,rfind是從後往前找的。

str.index(sub[, start[, end]])

類似于find(), 但在找不到子字元串的時候會引發ValueError

str.index('python')

---
ValueError: substring not found           

str.count(sub[, start[, end]])

這個函數會在字元串中去查找sub在其中[start, end]範圍内非重疊出現的次數。

print(str.count('a'))
print(str.count('a', 5, 12))

---
6
3           

接下來讓我們看看字元串操作相關的函數:

str.split(sep=None, maxsplit=-1)

這個方法可以按照指定的分隔符(sep),把字元串分隔成清單。

str = 'user_admin_id_123'
str.split('_')

---
['user', 'admin', 'id', '123']           

整個方法裡的maxsplit是進行多少次拆分,比如1為一次拆分,也就是會傳回2個元素。預設值為-1,意思是不限制拆分次數。

str.split('_', 1)

---
['user', 'admin_id_123']           

str.rsplit(sep=None, maxsplit=-1)

和split方法相似,隻是方向不同。這個是從後向前擷取。

str.rsplit('_')

---
['user', 'admin', 'id', '123']           

這段代碼可以看到功能上是完全一樣的,如果我們把maxsplit加進去,就能看到方向上的不同:

str.rsplit('_', 1)

---
['user_admin_id', '123']           

這樣就能清晰看到,rsplit是從後面開始拆分的。

str.join(iterable)

join的功能和split可以看成是相反的,是使用指定的字元串,把一個容器中的元素連接配接成一整個字元串

str = ['user', 'admin', 'id', '123']
'_'.join(str)

---
'user_admin_id_123'           

str.strip([chars])

去除字元串左右兩側的指定字元, chars參數為置頂要溢出字元的字元串,預設移除空白符。

str = ' chaheng '
str.strip(' ')

---
'chaheng'           

這個函數有兩個伴生函數,一個是rstrip, 從方法名應該能猜的出來,這是去掉字元串右側的指定字元,另一個是lstrip, 這是去除左側的指定字元。

str.rstrip(' ')
str.lstrip(' ')

---
' chaheng'
'chaheng '           

len()函數可以擷取目前字元串的長度

len(str)

---
9           

str.replace(old, new[, count])

可以替換對應的字元串,将old都替稱為new。count則是替換次數。比如一個字元串内出現了十次old, 我``count給的5, 則隻替換前5次出現的old`字元串。

str = 'abcabcabcabcabcabc'
str.replace('a', 'e')
str.replace('a', 'e', 2)

---
'ebcebcebcebcebcebc'
'ebcebcabcabcabcabc'           

可以注意一下兩次列印的差別。

這次就不留練習題了,字元串的查詢和操作函數屬于重中之重,大家最好是多去練習幾遍,将其中的方法記會杯熟。

好,今天就到這裡。咱們下節課再見。