字符串(3)
你们又听见有吩咐古人的话,说:“不可背誓,所起的誓,总要向主谨守”。只是我告诉你们,什么誓都不可起,不可指着天起誓,因为天是神的座位。不可指着地起誓,因为地是他的脚蹬,也不可指着耶路撒冷起誓,因为耶路撒冷是大君的京城。又不可指着你的头起誓,因为你不能使一根头发变黑变白了。你的话,是,就说是。不是,就说不是。若再多说,就是出于那恶者。(Matthew 5:33-37)
字符串(3)
字符串是一个话题中心,还要再继续。
例如这样一个字符串python
,还记得前面对字符串的定义吗?它就是字符:p,y,t,h,o,n,排列起来。这种排列是非常严格的,不仅仅是字符本身,而且还有顺序,换言之,如果某个字符换了,就变成一个新字符串了;如果这些字符顺序发生变化了,也成为了一个新字符串。
在Python中,把像字符串这样的对象类型(后面还会冒出来类似的其它有这种特点的对象类型,比如列表),统称为序列。
顾名思义,序列就是“有序排列”。
比如水泊梁山的108个好汉(里面分明也有女的,难道女汉子是从这里来的吗?),就是一个“有序排列”的序列。从老大宋江一直排到第108位金毛犬段景住。在这个序列中,每个人有编号,编号和每个人一一对应。1号是宋江,2号是卢俊义。反过来,通过每个人的姓名,也能找出他对应的编号。武松是多少号?14号。李逵呢?22号。
在Python中,给这些编号取了一个文雅的名字,叫做索引(别的编程语言也这么称呼,不是Python独有的。)。
索引和切片
梁山好汉,从1排到108,就是索引。
再看Python的字符串:
>>> lang = "study python">>> lang[0]'s'>>> lang[1]'t'
有一个字符串,要得到这个字符串的第一个单词s
,可以用lang[0]
。当然,如果你不愿意让变量lang来指向那个字符串,也可以这样做:
>>> "study python"[0]'s'
效果是一样的。因为lang是标签,就指向了"study python"
字符串。当让执行lang[0]
的时候,就是要转到那个字符串对象,如同上面的操作一样。只不过,如果不用lang这么一个变量,后面如果再写,就费笔墨了,要每次都把那个字符串写全了。为了省事,还是复制给一个变量吧。变量就是字符串的代表了。
字符串这个序列的排序方法跟梁山好汉有点不同,第一个不是用数字1表示,而是用数字0表示。不仅仅Python,其它很多语言都是从0开始排序的。为什么这样做呢?这就是规定。当然,这个规定是有一定优势的。此处不展开,有兴趣的网上去google一下,有专门对此进行解释的文章。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|---|
s | t | u | d | y | p | y | t | h | o | n |
上面的表格中,将这个字符串从第一个到最后一个进行了排序,特别注意,两个单词中间的那个空格,也占用了一个位置。
空格也是一个字符。“无”不完全等于“没有”。
通过索引能够找到该索引所对应的字符,那么反过来,能不能通过字符,找到其在字符串中的索引值呢?怎么找?
用字符串的一个方法——index:
>>> lang.index("p")6
就这样,是不是已经能够和梁山好汉的例子对上号了?但有区别,第一个的索引值是0。
如果某一天,宋大哥站在大石头上,向着各位弟兄大喊:“兄弟们,都排好队。”等兄弟们排好之后,宋江说:“现在给各位没有老婆的兄弟分配女朋友,我这里已经有了名单,我念到的兄弟站出来。不过我是按照序号来念的。第29号到第34号先出列,到旁边房子等候分配女朋友。”
继续应用前述字符串,lang[1]
能够得到字符串的第二个字符t
,就相当于从字符串中把这个“切”出来了。不过,我们这么“切”却不影响原来字符串的完整性,当然可以理解为将那个字符t
复制一份拿出来了。
那么宋江大哥没有一个一个“切”,而是一下将几个兄弟叫出来。在Python中也能做类似事情。
>>> lang'study python' #在前面“切”了若干的字符之后,再看一下该字符串,还是完整的。>>> lang[2:9]'udy pyt'
通过lang[2:9]
要得到多个(不是一个)字符,从返回的结果中可以看出,我们得到的是序号分别对应着2,3,4,5,6,7,8
(跟上面的表格对应一下)字符(包括那个空格)。也就是,这种获得部分字符的方法中,能够得到开始需要的以及最后一个序号之前的所对应的字符。有点拗口,自己对照上面的表格数一数就知道了。简单说就是包括开头,不包括结尾——前包括,后不包括。
上述,不管是得到一个还是多个,通过索引范围得到字符的过程,称之为切片。
切片是一个很有意思的东西。可以“切”出不少花样呢?
>>> lang'study python'>>> b = lang[1:] #得到从1号到最末尾的字符,这时最后那个需要不用写>>> b'tudy python'>>> c = lang[:] #得到所有字符>>> c'study python'>>> d = lang[:10] #得到从第一个到10号之前的字符>>> d'study pyth'
在获取切片的时候,如果冒号的:
- 前面不写数字,就表示从字符串的第一个开始(包括第一个);
- 后面的序号不写,就表示到字符串的到最末一个字符结束(包括最后一个)。
lang[:10]
的效果和lang[0:10]
是一样的。
>>> e = lang[0:10]>>> e'study pyth'
那么,lang[1:]
和lang[1:11]
效果一样吗?
请思考后作答。
>>> lang[1:11]'tudy pytho'>>> lang[1:]'tudy python'
不一样。
原因就是前述所说的,如果冒号后面有数字,所得到的切片,不包含该数字所对应的序号(前包括,后不包括)。那么,是不是可以这样呢?lang[1:12]
,不包括12号(事实没有12号),是不是可以得到1到11号对应的字符呢?
>>> lang[1:12]'tudy python'>>> lang[1:13]'tudy python'
果然是。并且不仅仅后面写12,写13,也能得到同样的结果。
但是,特别要提醒,这种获得切片的做法在编程实践中是不提倡的。特别是如果后面要用到循环的时候,这样做或许在什么时候遇到麻烦。
如果在切片的时候,冒号左右都不写数字,就是前面所操作的c = lang[:]
,其结果是变量c的值与原字符串一样,也就是“复制”了一份。注意,这里的“复制”我打上了引号,意思是如同复制,是不是真的复制呢?可以用下面的方式检验一下
>>> id(c)3071934536L>>> id(lang)3071934536L
id()
的作用就是查看该对象在内存地址(就是在内存中的位置编号)。从上面可以看出,两个的内存地址一样,说明c和lang两个变量指向的是同一个对象。用c=lang[:]
的方式,并没有生成一个新的字符串,而是将变量c这个标签也贴在了原来那个字符串上了。
>>> lang = "study python">>> c = lang
如果这样操作,变量c和lang是不是指向同一个对象呢?或者两者所指向的对象内存地址如何呢?用id()
函数查看便知。
字符串有索引,能得到切片。不仅如此,还有更多操作。
字符串基本操作
字符串是一种序列,所有序列都有如下基本操作,这是序列共有的操作。
- len():求序列长度
- :连接2个序列
- : 重复序列元素
- in :判断元素是否存在于序列中
- max() :返回最大值
- min() :返回最小值
- cmp(str1,str2) :比较2个序列值是否相同
逐个演示,方能理解:
+
>>> str1 + str2'abcdabcde'>>> str1 + "-->" + str2'abcd-->abcde'
这其实就是拼接,不过在这里,看官应该有一个更大的观念,我们现在只是学了字符串这一种序列,后面还会遇到列表、元组两种序列,都能够如此实现拼接。
in
>>> "a" in str1True>>> "de" in str1False>>> "de" in str2True
in
用来判断某个字符串是不是在另外一个字符串内,或者说判断某个字符串内是否包含另外一个字符串(这个字符串被称为子字符串),如果包含,就返回True
,否则返回False
。
最大值和最小值
>>> max(str1)'d'>>> max(str2)'e'>>> min(str1)'a'
在英文字典中,所有的字母都有一个排序,我们称之为“字典顺序”。
而每个字符,也都通过编码对应着一个数字,它们都会有一定的顺序。min()
和max()
就是根据这个顺序获得最小值和最大值,然后对应出相应的字符。读者可以google有关字符编码,或者ASCII编码什么的,很容易查到。
比较
>>> cmp(str1, str2)-1
将两个字符串进行比较,也是首先将字符串中的符号转化为对应编码的数字,然后比较。如果返回的数值小于零,说明第一个小于第二个;等于0,则两个相等;大于0,第一个大于第二个。为了能够明白其所以然,进入下面的分析。
>>> ord('a')97>>> ord('b')98>>> ord(' ')32
ord()
是一个内建函数,能够返回某个字符(注意,是一个字符,不是多个字符组成的串)所对一个的ASCII值(是十进制的),字符a在ASCII中的值是97,空格在ASCII中也有值,是32。顺便说明,反过来,根据整数值得到相应字符,可以使用chr()
:
>>> chr(97)'a'>>> chr(98)'b'
于是,就得到如下比较结果了:
>>> cmp("a","b") #a-->97, b-->98, 97小于98,所以a小于b-1>>> cmp("abc","aaa") 1>>> cmp("a","a")0
看看下面的比较,是怎么进行的呢?
>>> cmp("ad","c")-1
在字符串的比较中,是两个字符串的第一个字符先比较,如果相等,就比较下一个,如果不相等,就返回结果。直到最后,如果还相等,就返回0。位数不够时,按照没有处理(注意,没有不是0,0在ASCII中对应的是NUL),位数多的那个天然大了。ad
中的a
先和后面的c
进行比较,显然a
小于c
,于是就返回结果-1
。
如果进行下面的比较,是最容易让人迷茫的。能不能根据刚才阐述的比较理解呢?
>>> cmp("123","23")-1>>> cmp(123,23) #也可以比较整数,这时候就是整数的直接比较了。1
如果读者阅读到这里,不知道你是否将上面的各项进行了实际操作?如果操作了,在Python 3中能成功吗?
上面的操作只能适用于Python 2,不适用Python 3。
Python 3中取消了cmp()
函数。那么在Python 3中怎么比较呢?
>>> str1 = "abc">>> str1 > str2False>>> str1 < str2True>>> str1 == str2False
用比较运算符,也可以得到比较结果。
“*”
字符串中的“乘法”,这个乘法,就是重复那个字符串的含义。在某些时候很好用的。比如我要打印一个华丽的分割线:
>>> str1*3'abcdabcdabcd'>>> print "-"*20 #不用输入很多个`-`--------------------
len()
要知道一个字符串有多少个字符,一种方法是从头开始,盯着屏幕数一数。哦,这不是计算机在干活,是键客在干活。
键客,不是剑客。剑客是以剑为武器的侠客;而键客是以键盘为武器的侠客。当然,还有贱客,那是贱人的最高境界,贱到大侠的程度,比如岳不群之流。
Python用len()
函数来获得字符串长度,不管Python 2还是Python 3。
>>> a = "hello">>> len(a)5
函数len(object)
,得到的结果就是该字符串长度。
>>> m = len(a) #把结果返回后赋值给一个变量>>> m5>>> type(m) #这个返回值(变量)是一个整数型,Python 3中返回的结果略有差别。<type 'int'>
对于字符串,作为序列的一种,除了具有上述几种通用的基本操作之外,还有很多别的方法。