正如《你真的知道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方法: