Python入门笔记(五) 字符串

第五篇学习笔记,内容和Python的字符串类型相关。

概述

python中的字符串是一种包含了一串字符的基本数据结构。字符串可以使用一对单引号或者双引号括起来。
当字符串内含有单引号或者双引号时,要用另外一种引号。而当单引号和双引号全都有的时候,需要使用三单引号或者三双引号。
其中使用三单引号或者三双引号可以创建字面引用,即按照原样处理三引号里面的所有字符。
需要注意的是,python中没有字符的概念,单个字符也是用字符串来实现的。

访问字符串

访问字符串中的某一个字符(当然,得到的不是字符而是字符串)可以使用一般访问数组的形式,如:

1
2
3
4
5
6
>>> a = 'abc'
>>> a[0]
'a'
>>> a[-1]
'c'
>>>

python中支持负数下标,下标-1表示最后一个字符,以此类推。
访问字符串中的一段字符则需要使用切片(在后续笔记中会提到)。

打印字符串

使用print函数可以打印字符串。在字符串前面加上一个r可以输出未转义的转义字符(即输出原始字符串),如:

1
2
>>> print(r"a  \t  b  \n  c")
a \t b \n c

要打印一些特殊的字符需要使用一些转义字符。常用的转义字符如下:

转义字符 作用(真实值)
\(在行尾时) 续行符
\\ 反斜杠符\
\' 单引号'
\" 双引号"
\0, \000 空字符
\a 响铃
\b 退格
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ooo 某个字符,其ascii码在八进制下为ooo
\xhh 某个字符,其ascii码在十六进制下为hh

作为特殊情况,\other输出\other,其中other是某个没有转义意义的字符,如p

拆分字符串

可以对字符串类型使用list()函数,从而将字符串中的每一个字符都拆出来,并且放置在一个序列之中。如:

1
2
3
>>> str1 = "abcabc"
>>> list(str1)
['a', 'b', 'c', 'a', 'b', 'c']

转换成字符串

可以使用str()或者repr()函数将某一个对象转换成为一个字符串。其中str()函数将对象转换成为一个用户容易读的形式,而repr()将对象转换成为python解释器容易理解的形式。需要根据用途使用这两个函数。
一般情况下,这两个函数的返回值并没有区别。但在某一些情况下会有一些不同。下举一例:

1
2
3
4
5
>>> dict = {'runoob': 'runoob.com', 'google': 'google.com'}
>>> str(dict)
"{'runoob': 'runoob.com', 'google': 'google.com'}"
>>> repr(dict)
"{'google': 'google.com', 'runoob': 'runoob.com'}"

字符串的运算

使用+可以将字符串连接起来。如:

1
2
3
4
>>> name = 'Abc'
>>> age = '123'
>>> name + age
'Abc123'

使用*可以重复输出字符串,如:

1
2
3
4
5
6
7
8
9
10
11
>>> age = '123'
>>> age * 2
'123123'
>>> age * 0.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
>>> age * -3
''
>>> age * 0
''

可知,当乘的数是负数或者0时,字符串为空。并且不能乘小数。
字符串之间的比较运算基于字符串的字典序。这里的字典序是在ASCII码(或unicode码)语境下。如:

1
2
3
4
5
6
>>> '11' > '2'
False
>>> 'abc' > '123'
True
>>> '啊' > 'zzzzzzzzzzzzzzzzzzzzz'
True

字符串的格式化

python中的字符串可以做到像c/c++中一样的格式化。格式化的方式一般为2种。

怀旧方式:标识符形式

字符串支持标识符方式的填充,如:

1
2
3
4
5
6
7
>>> msg = "I am %s." %("huyutou")
>>> msg
'I am huyutou.'
>>> a, b = 10, 1.0
>>> msg = "get %d and %f." %(a, b)
>>> msg
'get 10 and 1.000000.'

标识符的使用方式几乎和c语言相同,下面列出一些主要的标识符:

标识符 对应替换目标
%s 字符串 (采用str()的显示)
%r 字符串 (采用repr()的显示)
%c 单个字符
%b 二进制整数
%d 十进制整数
%i 十进制整数
%o 八进制整数
%x 十六进制整数
%e 指数 (基底写为e)
%E 指数 (基底写为E)
%f 浮点数
%F 浮点数,与上相同
%g 指数(e)或浮点数 (根据显示长度)
%G 指数(E)或浮点数 (根据显示长度)
%% 字符%

对于标识符还可以追加一些额外的参数,如:
%[(name)][flags][width][.precision]type
其中(name)表示当使用字典来匹配模板时,要匹配的键的名称。如:

1
2
3
>>> dict = {"zqy":"nb", "is":"is not"}
>>> print("zqy %(is)s %(zqy)s." % (dict))
zqy is not nb.

flag可以为+,-,`,0,分别表示加上一个正号(字符串是向右对齐),加上一个负号(字符串是向左对齐),前导部分用空格填充,前导部分用0填充。width表示输出的宽度,当实际宽度小于width时根据数据类型采用不同的字符填充前导部分。(字符串是不会填充前导0的)。.precision用于控制小数点后的位数。type`即为表中列出的一系列标识符。

新方式:format函数

使用字符串对象的format函数可以容易地实现字符串中对应内容的填充。
format函数可以接受不限个参数,并且填充的时候可以不按照顺序填充。如:

1
2
>>> "{1} {0} {1}".format("hello", "world")  # 设置指定位置
'world hello world'

可以看出,只要在对应的大括号里面写上format内参数的下标,就可以输出对应的参数。
也可以传入一个元组,一次性按顺序填入多个值。如:

1
2
3
4
5
>>> tp = (1, 2, 3, 4)
>>> print("{} {} {}".format(*tp))
1 2 3
>>> print("{} {} {} {}".format(*tp))
1 2 3 4

还可以在format函数里面对参数进行命名,并且在大括号里面使用参数的名称,这样就可以像使用字典一样根据参数的名称填入对应的参数。如:

1
2
>>> print("{name} {P}".format(name = 2, P = 1))
2 1

使用字典做类似的事情也是可以的,但是要在字典之前加入两个*号。如:

1
2
3
>>> dict = {"zqy":"nb", "is":"is not"}
>>> print("zqy {is} {zqy}.".format(**dict))
zqy is not nb.

或者使用如下的方法:

1
2
dict1 = {'name': 1, 'age': 2}
print("{0[name]} {0[age]}".format(dict1)) #输出为1 2

甚至还可以做到用列表来索引参数。如:

1
2
3
4
>>> list = ["nb", "is not"]
>>> list2 = ["Why"]
>>> >>> print("zqy {0[1]} {0[0]}. {1[0]}?".format(list, list2))
zqy is not nb. Why?

中括号里面的就是列表中要填充元素的下标了。
还可以向str.format()中传入对象,如:

1
2
3
4
5
class A:
pass
a = A()
a.b = 1
print('{0.b}'.format(a)) # 输出1

可以看出,一般来说可以使用传入参数的索引来指向某个参数,如上述在列表的中括号前面加上0和1表示是第几个列表。
以上这些可以任意的组合使用。如:

1
2
3
4
5
6
7
8
dict1 = {'name': 1, 'age': 2}
list1 = [3, 4, 5]
class A:
pass
a = A()
a.pp = 6
print("{0} {1[2]} {2[name]} {3.pp} {other}".format(8, list1, dict1, a, other = 10))
# 输出为8 5 1 6 10

除了填充之外,还有格式化的多种方式,以下以公式形式列出:(冒号放在与填充相关的之后,如{0:.2f}
:[[fill]align][sign][#][0][width][,][.precision][type]
fill为空白处填充的字符,align为对齐方式(一般配合width使用,width意义见下),用一个字符表示:左对齐为<,右对齐(默认情况)为>
居中为^=为右对齐,并将符号放置在填充字符的左侧,且只对数字类型有效,即符号+填充符+数字。以下举一些例子:

1
2
3
4
5
6
7
8
>>> '{:>10}'.format(4)
' 4'
>>> '{:q>10}'.format(4)
'qqqqqqqqq4'
>>> '{:q^10}'.format(4)
'qqqq4qqqqq'
>>> '{:q=10}'.format(-4)
'-qqqqqqqq4'

sign表示是否显示符号,用一个字符表示:为+时正负数都显示符号,为-时仅负数显示符号,为空格时正数加空格,负数加负号。如:

1
2
3
4
5
6
7
8
>>> '{:< 10}'.format(4)
' 4 '
>>> '{:<+10}'.format(4)
'+4 '
>>> '{:>-10}'.format(4)
' 4'
>>> '{:=-10}'.format(-4)
'- 4'

#为一个开关,如果该位置有#号则对于某些特殊的数,会显示某种特殊形式,如二/八/十六进制会显示0b/0o/0x的前缀。如:

1
2
3
4
>>> '{:#b}'.format(0b0101001)
'0b101001'
>>> '{:#x}'.format(0x0122FFFF01001)
'0x122ffff01001'

0为一个开关,如果该位置有0对于长度不足width的数会在前面补足前导0。如:

1
2
>>> '{:09}'.format(1223)
'000001223'

width表示格式化位所占用的宽度,当总长度不足宽度的时候采用各种填充方法使总长度达到宽度,总长度大于宽度时按原样输出。如:

1
2
3
4
>>> '{:9}'.format(1223)
' 1223'
>>> '{:9}'.format(121111111111111111111123)
'121111111111111111111123'

,为一个开关,如果该位置有,对于数字会增加分割符。如:

1
2
>>> '{:,}'.format(1000000000)
'1,000,000,000'

.precisiontype的意义和旧版相似,在此不赘述。一个特殊情况是type%时显示百分比(默认为小数点后6位),如:

1
2
>>> '{:%}'.format(1000000000)
'100000000000.000000%'

需要额外注意的是,使用了format()函数,要在字符串中输出大括号需要用转义字符,即{{(输出{)和}}(输出})。

与单个字符有关的函数

ord()chr()是两个和字符使用有关的函数。前者可以返回一个字符的ASCII码(或unicode码),后者可以返回一个ASCII码(或unicode码)对应的字符。如:

1
2
3
4
5
6
7
8
>>> ord("a")
97
>>> chr(95)
'_'
>>> ord('上')
19978
>>> chr(19978)
'上'

ord()只能接受一个字符,否则报错。chr()同理。

字符串的大小写的修改

title()

输入为

1
2
3
name = 'abc'
name = 'aBc'
name = 'ABC'

对于任意一种,输出name.title()都是

1
'Abc'

并且有:

1
2
3
4
5
6
7
8
9
>>> name = 'abc123'
>>> name.title()
'Abc123'
>>> name = '123abc'
>>> name.title()
'123Abc'
>>> name = 'aBc123abC'
>>> name.title()
'Abc123Abc'

说明该函数作用是将一段英文的开头字母变为大写,其余均变为小写。对每一段英文字母(即每一个单词)都进行这样的变换。当分隔符是其他符号,如下划线的时候亦如此

capitalize()

capitalize的使用可以使字符串的第一个英文字符变为大写,而对其他的英文字符不产生影响。如:

1
2
3
>>> a = "it is good."
>>> a.capitalize()
'It is good.'

lower(),upper()

有如下输入输出:

1
2
3
4
5
6
7
>>> name = 'aBcD'
>>> name.upper()
'ABCD'
>>> name.lower()
'abcd'
>>> name
'aBcD'

说明这两个函数和c++的tolower(),toupper()意义相似,都可以将字母格式化为大/小写

swapcase()

使用swapcase()交换整个字符串中大小写的格式。如:

1
2
3
>>> a = 'aBcDeFg'
>>> a.swapcase()
'AbCdEfG'

字符串的判断

isalnum()用于判断一个字符串非空并且字符全部是字母或阿拉伯数字。isalpha()isdigit()则分别用来检测对应的全为字母/阿拉伯数字的情况。
检测数字的情况分为多种,其中isdigit()最为万能,可以检测包含阿拉伯数字在内的多种数字,但是检测不了汉字数字。使用isnumeric()可以检测汉字数字。
islower(),isupper(),isspace()同理。istitle()可以判断字符串是不是标题格式。isdemical()可以判断字符串是否仅包含十进制字符。
以上函数都是作为字符串对象的方法存在的。

字符串的相关操作

以下操作均为字符串对象的方法。

查找某一个字符串是否出现

使用in或者not in判断一个字符串在整个字符串中出现/不出现。如:

1
2
3
4
5
>>> a = "abcde"
>>> "bc" in a
True
>>> "efg" not in a
True

使用find(pattern, begin = 0, end = len(str))可以在指定区间内从左到右寻找要匹配的字符串,并且返回该字符串第一个字符的下标。
使用index(pattern, begin = 0, end = len(str))函数也可以,但是前者找不到会返回-1,后者会报错。
类似的有rfindrindex,这两个寻找的时候是从右到左。如:

1
2
3
4
5
6
7
8
9
10
11
>>> a = "abcabcabc"
>>> a.rfind("abc", 0)
6
>>> a.find("abc", 0)
0
>>> a.index("abc", 0)
0
>>> a.index("aaa", 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found

数一个字符串出现了几次

使用count()方法数一个字符串在另一个串内出现了几次。该方法的语法为str.count(sub, start = 0, end = len(string)),其中sub为要查找的字串。如:

1
2
3
4
5
6
>>> 'aaaaa'.count('aa')
2
>>> 'excite'.count('e', 1, 4)
0
>>> 'excite'.count('e', 1, 11)
1

可以看出,count()查找的字串是不相互重叠的。

分割和连成字符串

使用split()方法把一个字符串分割,得到一个列表。该方法语法为str.split(str = "", num = string.count(str))。其中str参数默认为所有的空字符,包括空格、换行、制表符等。num参数表示最终从前到后分割出num+1个字符串,默认为全部分割。如:

1
2
3
4
5
6
7
8
9
10
>>> 'a#b#c#d'.split('#', 0)
['a#b#c#d']
>>> 'a#b#c#d'.split('#', 1)
['a', 'b#c#d']
>>> 'a#b#c#d'.split('#', 2)
['a', 'b', 'c#d']
>>> 'a#b#c#d'.split('#', 3)
['a', 'b', 'c', 'd']
>>> 'a#b#c#d'.split('#', -1)
['a', 'b', 'c', 'd']

使用splitlines()方法把一个字符串按照行分割,即按照换行符,回车符分割。该方法语法为str.splitlines([keepends]),其中keepends为
布尔值,默认为False,表示分割后行末不保留换行符号。若为True则保留。
使用join()方法把一个包含字符串的序列连成一个字符串。该方法语法为str.join(sequence),其中sequence为某个序列结构。该方法可视为split()
逆方法,因为它连成的字符串之间的分割符即为str。如:

1
2
3
4
>>> ' '.join(('a', 'b'))
'a b'
>>> '#'.join(['a', 'b', 'c', 'd'])
'a#b#c#d'

判断一个字符串是否为前/后缀

使用startswith()方法判断一个字符串是否是另一个的前缀。该方法语法为str.startswith(substr, beg = 0, end = len(string)),意义和前几个方法基本相同。
使用endswith()方法判断一个字符串是否是另一个的后缀。语法和startswith()基本相同。如:

1
2
3
4
5
6
7
8
>>> 'ssss'.startswith('ss')
True
>>> 'ssss'.startswith('sa')
False
>>> 'ssss'.endswith('ss')
True
>>> 'ssss'.endswith('as')
False

替换字符串

使用replace()方法替换一个字符串中的某些模式串。该方法语法为str.replace(old, new[, max])old表示被替换的串,new表示新串,max表示最多替换次数,省略表示全部替换。如:

1
2
3
4
>>> 'aaaaa'.replace('a', 'b', 3)
'bbbaa'
>>> 'aaaaa'.replace('aa', 'b')
'bba'

字符串的样式调整

使用zfill(width)可以返回长度为width的字符串,其中原字符串向右对其,前面不足的部分使用0填充。如:

1
2
3
>>> a = "123z"
>>> a.zfill(6)
'00123z'

使用strip()去除字符串两端的空白字符。特别的,使用lstrip()仅去除字符串左端的空白字符,使用rstrip()仅去除字符串右端的空白字符。
使用center()方法可以使字符串居中。该方法的语法为str.center(width[, fillchar]),其中width为总宽度,fillchar为填充到总宽度所用的字符。如:

1
2
>>> s.center(10, '0')
'000aaa0000'

使用ljust()rjust()方法分别可以使字符串左居中和右居中,语法和center()相同。