正如《你真的知道Python的字符串是什麼嗎?》所寫,Python 中字符串是由 Uniocde 編碼的字符組成的不可變序列,它具有與其它序列共有的一些操做,例如判斷元素是否存在、拼接序列、切片操做、求長度、求最值、求元素的索引位置及出現次數等等。python
除此以外,它還有不少特有的操做,值得咱們時常溫故學習,因此,今天我就跟你們繼續聊聊字符串。正則表達式
本文主要介紹 Python 字符串特有的操做方法,好比它的拼接、拆分、替換、查找及字符判斷等使用方法,辨析了一些可能的誤區。最後,還作了兩個擴展思考:爲何 Python 字符串不具有列表類型的某些操做呢,爲何它不具有 Java 字符串的一些操做呢?兩相比較,但願能幫助你透徹地理解——Python 的字符串到底怎麼用?編程
字符串的拼接操做最經常使用,我專門爲這個話題寫過一篇《詳解Python拼接字符串的七種方式》,建議你回看。數組
在此,簡單回顧一下:七種拼接方式從實現原理上劃分爲三類,即格式化類(%佔位符、format()、template)、拼接類(+操做符、類元祖方式、join())與插值類(f-string),在使用上,我有以下建議——微信
當要處理字符串列表等序列結構時,採用join()方式;拼接長度不超過20時,選用+號操做符方式;長度超過20的狀況,高版本選用f-string,低版本時看狀況使用format()或join()方式。
不敢說字符串就只有這七種拼接方式,但應該說它們是最多見的了。有小夥伴說,我寫漏了一種,即字符串乘法 ,能夠重複拼接自身。沒錯,從結果上看,這是第八種拼接方式,視爲補充吧。app
關於字符串拼接,還得補充一個建議,即在複雜場景下,儘可能避免使用以上幾類原生方法,而應該使用外置的強大的處理庫。好比在拼接 SQL 語句的時候,常常要根據不一樣的條件分支,來組裝不一樣的查詢語句,並且還得插入不一樣的變量值,因此當面臨這種複雜的場景時,傳統拼接方式只會加重代碼的複雜度、下降可讀性和維護性。使用 SQLAlchemy
模塊,將有效解決這個問題。機器學習
在字符串的幾種拼接方法中,join() 方法能夠將列表中的字符串元素,拼接成一個長的字符串,與此相反,split() 方法能夠將長字符串拆分紅一個列表。前面已說過,字符串是不可變序列,因此字符串拆分過程是在拷貝的字符串上進行,並不會改變原有字符串。編程語言
split() 方法可接收兩個參數,第一個參數是分隔符,即用來分隔字符串的字符,默認是全部的空字符,包括空格、換行(n)、製表符(t)等。拆分過程會消耗分隔符,因此拆分結果中不包含分隔符。工具
s = 'Hello world' l = '''Hi there , my name is Python貓 Do you like me ? ''' # 不傳參數時,默認分隔符爲全部空字符 s.split() >>> ['Hello', 'world'] s.split(' ') >>> ['Hello', 'world'] s.split(' ') >>> ['Hello world'] # 不存在兩個空格符 s.split('world') >>> ['Hello', ''] # 空字符包括空格、多個空格、換行符等 l.split() >>> ['Hi', 'there', ',', 'my', 'name', 'is', 'Python貓', 'Do', 'you', 'like', 'me', '?']
split() 方法的第二個參數是一個數字,默認是缺省,缺省時全分隔,也能夠用 maxsplit 來指定拆分次數。學習
# 按位置傳參 l.split(' ',3) >>> ['Hi', 'there', ',', 'my name is Python 貓\nDo you like me ?\n'] # 指定傳參 l.split(maxsplit=3) >>> ['Hi', 'there', ',', 'my name is Python 貓\nDo you like me ?\n'] # 錯誤用法 l.split(3) --------------- TypeError Traceback (most recent call last) <ipython-input-42-6c16d1a50bca> in <module>() ----> 1 l.split(3) TypeError: must be str or None, not int
split() 方法是從左往右遍歷,與之相對,rsplit() 方法是從右往左遍歷,比較少用,可是會有奇效。
拆分字符串還有一種方法,即 splitlines() ,這個方法會按行拆分字符串,它接收一個參數 True 或 False ,分別決定換行符是否會被保留,默認值 False ,即不保留換行符。
# 默認不保留換行符 'ab c\n\nde fg\rkl\r\n'.splitlines() >>> ['ab c', '', 'de fg', 'kl'] 'ab c\n\nde fg\rkl\r\n'.splitlines(True) >>> ['ab c\n', '\n', 'de fg\r', 'kl\r\n']
替換字符串包括以下場景:大小寫替換、特定符號替換、自定義片斷替換......
再次說明,字符串是不可變對象,如下操做並不會改變原有字符串。
以上這些方法都很明瞭,使用也簡單,建議你親自試驗一下。這裏只說說 strip() 方法,它比較經常使用,能夠去除字符串先後的空格,不只如此,它還能夠刪除首末位置的指定的字符。
s = '******Hello world******' s.strip('*') >>> 'Hello world'
查找字符串中是否包含某些內容,這是挺經常使用的操做。Python 中有多種實現方式,例如內置的 find() 方法,可是這個方法並不經常使用,由於它僅僅告訴你所查找內容的索引位置,而在一般狀況下,這個位置並非咱們的目的。
find() 方法與 index() 方法的效果同樣,它們的最大的區別只在於,找不到內容時的返回值不一樣,一個返回 -1,一個拋出異常 :
s = 'Hello world' s.find('cat') >>> -1 s.index('cat') >>> ValueError Traceback (most recent call last) <ipython-input-55-442007c50b6f> in <module>() ----> 1 s.index('cat') ValueError: substring not found
以上兩個方法,只能用來知足最簡單的查找需求。在實戰中,咱們經常要查找特定模式的內容,例如某種格式的日期字符串,這就得藉助更強大的查找工具了。正則表達式和 re 模塊就是這樣的工具,正則表達式用來定製匹配規則,re 模塊則提供了 match() 、find() 及 findall() 等方法,它們組合起來,能夠實現複雜的查找功能。限於篇幅,從此再對這兩大工具作詳細介紹,這裏有一個簡單的例子:
import re datepat = re.compile(r'\d+/\d+/\d+') text = 'Today is 11/21/2018. Tomorrow is 11/22/2018.' datepat.findall(text) >>> ['11/21/2018', '11/22/2018']
判斷字符串是否(只)包含某些字符內容,這類使用場景也很常見,例如在網站註冊時,要求用戶名只能包含英文字母和數字,那麼,當校驗輸入內容時,就須要判斷它是否只包含這些字符。其它經常使用的判斷操做,詳列以下:
上文內容都是 Python 字符串特有的操做方法,相信讀完以後,你更清楚知道 Python 可以作什麼了。
可是,這還不足以回答本文標題的問題——你真的知道 Python 的字符串怎麼用嗎?這些特有的操做方法,再加上以前文章提到的序列共有的操做、字符串讀寫文件、字符串打印、字符串Intern機制等等內容,才差很少可以回答這個問題。
儘管如此,爲了體現嚴謹性,我試着再聊聊「Python 字符串不能夠作的事」,從相反的維度來補充回答這個問題。下面是開拓思惟,進行頭腦風暴的時刻:
(1)受限的序列
與典型的序列類型相比,字符串不具有列表的以下操做:append()、clear()、copy()、insert()、pop()、remove(),等等。這是爲何呢?
有幾個很好理解,即append()、insert()、pop() 和 remove(),它們都是對單個元素的操做,可是,字符串中的單個元素就是單個字符,一般沒有任何意義,咱們也不會頻繁對其作增刪操做,因此,字符串沒有這幾個方法也算合理。
列表的 clear() 方法會清空列表,用來節省內存空間,其效果等同於 anylist[:] = []
,可是,奇怪的是,Python 並不支持清空/刪除操做。
首先,字符串沒有 clear() 方法,其次,它是不可變對象,不支持這種賦值操做 anystr[:] = ''
,也不支持 del anystr[:]
操做:
s = 'Hello world' s[:] = '' >>> 報錯:TypeError: 'str' object does not support item assignment del s[:] >>> 報錯:TypeError: 'str' object does not support item deletion
固然,你也別想經過 del s
來刪除字符串,由於變量名 s 只是字符串對象的引用 (挖坑,之後寫寫這個話題),只是一個標籤,刪除標籤並不會直接致使對象實體的消亡。
如此看來,想要手動清空/刪除 Python 字符串,彷佛是無解。
最後還有一個 copy() 方法,這就是拷貝嘛,但是字符串也沒有這個方法。爲何呢?難道拷貝字符串的場景很少麼?在這點上,我也沒想出個因此然來,擱置疑問。
經過以上幾個經常使用列表操做的比較,咱們能夠看出字符串這種序列是挺受限的。列表能夠當作多節車箱連接成的火車,而字符串感受就只像多個座椅聯排成的長車箱,真是同源不一樣相啊。
(2)比就比,誰怕誰
接下來,又到了 Python 字符串與 Java 字符串 PK 的時刻。在上一篇文章《你真的知道Python的字符串是什麼嗎?》中,它們已經在對象定義的角度切磋了兩回合,勝利的天平倒向了 Python,此次看看會比出個啥結果吧。
Java 中有 比較字符串
的方法,即 compareTo() 方法與 equals() 方法,前一個方法逐一比較兩個字符串的字符編碼,返回一個整型的差值,後一個方法在總體上比較兩個字符串的內容是否相等。
Python 字符串沒有這兩個單獨的方法,但要實現相似的功能卻很簡便。 先看例子:
myName = "Python貓" cmpName = "world" newName = myName # 直接用比較符號進行compare myName > cmpName >>> False myName == newName >>> True cmpName != newName >>> True # 比較是否同一對象 myName is cmpName >>> False myName is newName >>> True
上例中,若是把賦值的字符串換成列表或者其它對象,這些比較操做也是能夠進行的。也就是說,做比較的能力 是 Python 公民們的一項基本能力,並不會由於你是字符串就給你設限,或者給你開特權。
與此相似,Python 公民們自帶求自身長度的能力 ,len() 方法是內置方法,能夠直接傳入任意序列參數,求解長度。Java 中則要求不一樣的序列對象,只能調用各自的 length() 方法。說個形象的比喻,Python 中共用一把秤,三教九流之輩都能拿它稱重,而Java 中有多把秤,你稱你的,我稱個人,你們「井水不犯河水」。
Python 中曾經有 cmp() 方法和 __cmp__()
魔術方法,但官方嫌棄它們雞肋,因此在Python 3 中移除掉了。雖然在 operator 模塊中還爲它留下了一脈香火,但保不定哪天就會完全廢棄。
import operator operator.eq('hello', 'name') >>> False operator.eq('hello', 'hello') >>> True operator.gt('hello', 'name') >>> False operator.lt('hello', 'name') >>> True
(3)牆上的門
在 Java 中,字符串還有一個強大的 valueOf() 方法,它能夠接收多種類型的參數,如boolean、char、char數組、double、float、int等等,而後返回這些參數的字符串類型。 例如,要把 int 轉爲字符串,能夠用 String.valueOf(anynum) 。
Python 字符串依然沒有這個單獨的方法,但要實現相同的功能卻很簡便。對Python來講,不一樣的數據類型轉換成字符串,那是小菜一碟,例如:
str(123) >>> '123' str(True) >>> 'True' str(1.22) >>> '1.22' str([1,2]) >>> '[1, 2]' str({'name':'python', 'sex':'male'}) >>> "{'name': 'python', 'sex': 'male'}"
而從字符串轉換爲其它類型,也不難,例如,int('123') 便可由字符串'123' 獲得數字 123。對比 Java,這個操做要寫成 Integer.parseInt('123')
。
在Java 的不一樣數據類型之間,那道分隔之牆矗立得很高,彷彿須要藉助一座更高的吊橋才能溝通兩邊,而在靈活的 Python 裏,你能夠很方便地打開牆上的那扇門,來往穿越。
小結一下,跟 Java 相比,Python 字符串確實沒有幾項方法,可是事出有因,它們的天賦能力可不弱,全部這些操做都能簡明地實現。一方面,Python 字符串作不到某些事,可是另外一方面,Python 能夠出色地作成這些事,孰優孰劣,高下立判。
寫文章貴在有始有終,如今給你們總結一下:本文主要介紹 Python 字符串特有的操做方法,好比它的拼接、拆分、替換、查找及字符判斷等使用方法,從正向回答,Python 字符串能作什麼?最後,咱們還從反向來回答了 Python 字符串不能作什麼?有些不能作,其實是 不爲,是爲了在其它地方更好地做爲,歸根到底,應該有的功能,Python 字符串全都有了。
本文中依然將 Python 與 Java 作了比較,有幾項小小的差別,背後反映的實際上是,兩套語言系統在世界觀上的差別。古人云,以銅爲鏡,能夠正衣冠。那麼,在編程語言的世界裏,以另外一種語言爲鏡,也更能看清這種語言的面貌。但願這種跨語言的思惟碰撞,能爲你擦出智慧的火花。
最後是福利時刻:本公衆號(Python貓)由清華大學出版社贊助,將抽獎送出兩本新書《深刻淺出Python機器學習》,截止時間到11月29日18:18,點擊 這個連接,立刻參與吧。
-----------------
本文原創並首發於微信公衆號【Python貓】,後臺回覆「愛學習」,免費得到20+本精選電子書。
擴展閱讀:
Java字符串比較方法:
https://blog.csdn.net/barryha...
Python3爲什麼取消cmp方法: