常用数据结构之字符串

字符串的定义

所谓字符串,就是由零个或多个字符组成的有限序列

s=a1a2an(0n)s = a_1a_2 \cdots a_n \,\,\,\,\, (0 \le n \le \infty)

我们把单个或多个字符用单引号或者双引号包围起来,就可以表示一个字符串。字符串中的字符可以是特殊符号、英文字母、中文字符、日文的平假名或片假名、希腊字母、Emoji 字符

s1 = 'hello, world!'
s2 = "你好,世界!❤️"
s3 = '''hello,
wonderful
world!'''
print(s1)
print(s2)
print(s3)

转义字符

可以在字符串中使用\(反斜杠)来表示转义

s1 = '\'hello, world!\''
s2 = '\\hello, world!\\'
print(s1)
print(s2)

输出一个带单引号或反斜杠的字符串

原始字符串

rR开头的字符串,这种字符串被称为原始字符串,在字符串'hello\n'中,\n表示换行;而在r'hello\n'中,\n不再表示换行,就是字符\和字符n

s1 = '\it \is \time \to \read \now'
s2 = r'\it \is \time \to \read \now'
print(s1)
print(s2)

说明:上面的变量s1中,\t\r\n都是转义字符。\t是制表符(table),\n是换行符(new line),\r是回车符(carriage return)相当于让输出回到了行首。

字符串的运算

拼接和重复

s1 = 'hello' + ', ' + 'world'
print(s1)    # hello, world
s2 = '!' * 3
print(s2)    # !!!
s1 += s2
print(s1)    # hello, world!!!
s1 *= 2
print(s1)    # hello, world!!!hello, world!!!

比较运算

对于两个字符串类型的变量,可以直接使用比较运算符来判断两个字符串的相等性或比较大小。那么字符串的大小比较比的是每个字符对应的编码的大小。例如A的编码是65, 而a的编码是97,所以'A' < 'a'的结果相当于就是65 < 97的结果,这里很显然是True

成员运算

可以用innot in判断一个字符串中是否包含另外一个字符或字符串

s1 = 'hello, world'
s2 = 'goodbye, world'
print('wo' in s1)      # True
print('wo' not in s2)  # False
print(s2 in s1)        # False

获取字符串长度

获取字符串长度跟获取列表元素个数一样,使用内置函数len

s = 'hello, world'
print(len(s))                 # 12
print(len('goodbye, world'))  # 14

索引和切片

因为字符串是不可变类型,所以不能通过索引运算修改字符串中的字符

s = 'abc123456'
n = len(s)
print(s[0], s[-n])    # a a
print(s[n-1], s[-1])  # 6 6
print(s[2], s[-7])    # c c
print(s[5], s[-4])    # 3 3
print(s[2:5])         # c12
print(s[-7:-4])       # c12
print(s[2:])          # c123456
print(s[:2])          # ab
print(s[::2])         # ac246
print(s[::-1])        # 654321cba

字符的遍历

方式一:

s = 'hello'
for i in range(len(s)):
    print(s[i])

方式二:

s = 'hello'
for elem in s:
    print(elem)

字符串的方法

假设我们有名为loker的字符串,字符串有名为bar的方法,那么使用字符串方法的语法是:loker.bar(),这是一种通过对象引用调用对象方法的语法,

s1 = 'hello, world!'
# 字符串首字母大写
print(s1.capitalize())  # Hello, world!
# 字符串每个单词首字母大写
print(s1.title())       # Hello, World!
# 字符串变大写
print(s1.upper())       # HELLO, WORLD!
s2 = 'GOODBYE'
# 字符串变小写
print(s2.lower())       # goodbye
# 检查s1和s2的值
print(s1)               # hello, world
print(s2)               # GOODBYE

说明:字符串是不可变类型

查找操作

想在一个字符串中从前向后查找有没有另外一个字符串,可以使用字符串的findindex方法。

s = 'hello, world!'
print(s.find('or'))      # 8
print(s.find('or', 9))   # -1
print(s.find('of'))      # -1
print(s.index('or'))     # 8
print(s.index('or', 9))  # ValueError: substring not found

findindex方法还有逆向查找(从后向前查找)的版本,分别是rfindrindex

s = 'hello world!'
print(s.find('o'))       # 4
print(s.rfind('o'))      # 7
print(s.rindex('o'))     # 7
# print(s.rindex('o', 8))  # ValueError: substring not found

性质判断

可以通过字符串的startswithendswith来判断字符串是否以某个字符串开头和结尾;还可以用is开头的方法判断字符串的特征,都返回布尔值。

s1 = 'hello, world!'
print(s1.startswith('He'))   # False
print(s1.startswith('hel'))  # True
print(s1.endswith('!'))      # True
s2 = 'abc123456'
print(s2.isdigit())  # False
print(s2.isalpha())  # False
print(s2.isalnum())  # True

说明:上面的isdigit用来判断字符串是不是完全由数字构成的,isalpha用来判断字符串是不是完全由字母构成的,这里的字母指的是 Unicode 字符但不包含 Emoji 字符,isalnum用来判断字符串是不是由字母和数字构成的。


字符串类型可以通过centerljustrjust方法做居中、左对齐和右对齐的处理。如果要在字符串的左侧补零,也可以使用zfill方法。

s = 'hello, world'
print(s.center(20, '*'))  # ****hello, world****
print(s.rjust(20))        #         hello, world
print(s.ljust(20, '~'))   # hello, world~~~~~~~~
print('33'.zfill(5))      # 00033
print('-33'.zfill(5))     # -0033

print函数输出字符串

a = 321
b = 123
print('%d * %d = %d' % (a, b, a * b))

可以用字符串的format方法来完成字符串的格式

a = 321
b = 123
print('{0} * {1} = {2}'.format(a, b, a * b))

Python 3.6 开始,格式化字符串还有更为简洁的书写方式,就是在字符串前加上f来格式化字符串,

a = 321
b = 123
print(f'{a} * {b} = {a * b}')
      

变量值

占位符

格式化结果

说明

3.1415926

{:.2f}

'3.14'

保留小数点后两位

3.1415926

{:+.2f}

'+3.14'

带符号保留小数点后两位

-1

{:+.2f}

'-1.00'

带符号保留小数点后两位

3.1415926

{:.0f}

'3'

不带小数

123

{:0>10d}

'0000000123'

左边补0,补够10位

123

{:x<10d}

'123xxxxxxx'

右边补x ,补够10位

123

{:>10d}

' 123'

左边补空格,补够10位

123

{:<10d}

'123 '

右边补空格,补够10位

123456789

{:,}

'123,456,789'

逗号分隔格式

0.123

{:.2%}

'12.30%'

百分比格式

123456789

{:.2e}

'1.23e+08'

科学计数法格式

修剪操作

字符串的strip方法可以帮我们获得将原字符串修剪掉左右两端指定字符之后的字符串,strip方法还有lstriprstrip两个版本

s1 = '   jackfrued@126.com  '
print(s1.strip())      # jackfrued@126.com
s2 = '~你好,世界~'
print(s2.lstrip('~'))  # 你好,世界~
print(s2.rstrip('~'))  # ~你好,世界

替换操作

用新的内容替换字符串中指定的内容,可以使用replace方法

s = 'hello, good world'
print(s.replace('o', '@'))     # hell@, g@@d w@rld
print(s.replace('o', '@', 1))  # hell@, good world

拆分与合并

字符串的split方法将一个字符串拆分为多个字符串(放在一个列表中)

s = 'I love you'
words = s.split()
print(words)            # ['I', 'love', 'you']
print('~'.join(words))  # I~love~you

split方法默认使用空格进行拆分,我们也可以指定其他的字符来拆分字符串

s = 'I#love#you#so#much'
words = s.split('#')
print(words)  # ['I', 'love', 'you', 'so', 'much']
words = s.split('#', 2)
print(words)  # ['I', 'love', 'you#so#much']

编码和解码

除了字符串str类型外,还有一种表示二进制数据的字节串类型(bytes)。所谓字节串,就是由零个或多个字节组成的有限序列。通过字符串的encode方法,我们可以按照某种编码方式将字符串编码为字节串,我们也可以使用字节串的decode方法,将字节串解码为字符串,