第 4 章 字符串
4.1字符串简介
很多人初学编程时,总是担心自己数学不行,潜意识里认为数学好才能编程。实际上,大多数程序员打交道最多的是“字符串”而不是“数字”。
Python 中除了数值类型,还有:字符串、列表、元组、字典、集合,这里把字符串单独拿出来讲解。
字符串的本质是:字符序列。Python 中字符串是不可变的,我们无法对原字符串做任何修改。但可以将字符串的一部分复制到新创建的字符串,达到“看起来修改”的效果。
Python 不支持单字符类型,单字符也是作为一个字符串使用的。
4.2字符串的编码
Python3 直接支持 Unicode编码,可以表示世界上任何书面语言的字符。Python3 的字符 默认就是 16 位 Unicode 编码,ASCII 码是 Unicode 编码的子集。
使用内置函数 ord()可以把字符转换成对应的 Unicode 码;
使用内置函数 chr()可以把十进制数字转换成对应的字符。
例:
print(ord('A'))
print(ord('高'))
print(chr(66))
执行后:
65
39640
'B'
4.3创建字符串
1.我们可以通过单引号或双引号创建字符串。
例:
b = 'my_name is "TOM"'
print(b)
print(type(b))
执行后:
my_name is "TOM" # 使用引号可以创建本身就包含引号的字符串,而不用使用转义字符
<class 'str'>
2.连续三个单引号或三个双引号,可以帮助我们创建多行字符串,也被称为文档字符串。
例:
resume = ''' name="gao"
company="sxt" age=18
lover="Tom"'''
print(resume)
print(type(resume))
执行后:
name="gao"
company="sxt" age=18
lover="Tom"
<class 'str'>
4.4空字符串
Python 允许空字符串的存在,不包含任何字符且长度为 0。
例:
c=''
print(c)
print(len(c))
执行后:
0
4.5转义字符
我们可以使用“\+特殊字符”,实现某些难以用字符表示的效果。比如:换行等。常见的 转义字符有这些:
转义字符 | 描述 |
\(在行尾时) | 续行符 |
\0 | 空 |
\\ | 真正的反斜杠符号\ |
\' | 单引号 |
\" | 双引号 |
\b | 退格(Backspace) |
\n | 换行 |
\t | 水平制表符,用于横向跳到下一制表位 |
例:
a = 'aaa\
bbb'
print(a)
print(type(a))
执行后:
aaabbb
<class 'str'>
4.6print()输出字符串
print() 函数用于将指定的对象输出到标准输出设备(如屏幕)或由 file 参数指定的文件。
格式:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
objects: 一个或多个要打印的对象,可以是任何数据类型。多个对象之间用逗号分隔。
sep: 用来连接多个对象之间的分隔符,默认是一个空格。
end: 在所有对象都被打印后添加的结尾字符,默认是一个换行符。
file: 指定输出的目标流,默认是 sys.stdout,即标准输出。
flush: 如果为 True,则强制立即刷新流,否则按系统默认行为处理。
例:
print("Hello", "world")
print("Hello", "world", sep="-")
print("Hello", end=" ")
print("world")
执行后:
Hello world # 默认使用空格分隔
Hello-world # 使用 '-' 分隔
Hello world # 不换行,结果是 "Hello world" 而不是 "Hello\nworld"
4.7input()输入字符串
input() 函数用于从标准输入(通常是键盘)读取一行文本,并返回用户输入的数据作为字符串。
格式:
input([prompt])
prompt: 可选参数,用于指定显示给用户的提示信息,是一个字符串。
例:
name = input("请输入你的名字: ")
print(f"你好, {name}!")
执行后:
请输入你的名字:
输入:
Bob
最终显示:
请输入你的名字: Bob
你好, Bob!
F 前缀:表示这是一个格式化字符串,它允许你在字符串字面量中嵌入表达式。这些表达式被放在花括号 {} 中。在字符串被创建时,这些表达式会被计算,并将其结果转换为字符串,然后插入到相应的位置。
{}:里面可以放置变量名,也可以是任意合法的表达式。如果只是变量名,那么该变量的值会被转换成字符串并插入到这个位置;如果是表达式,表达式的计算结果会被转换为字符串并插入。
4.8 + 实现字符串的拼接
1.可以使用 + 将多个字符串拼接起来。
(1)如果+两边都是字符串,则拼接。
(2)如果+两边都是数字,则加法运算。
(3)如果+两边类型不同,则抛出异常。
例:
a=’aa’+’bb’
print(a)
执行后:
’aabb’
2.可以将多个字面字符串直接放到一起实现拼接,但不能是空字符串’’。
例:
a=’aa’’bb’
print(a)
执行后:
’aabb’
注意:在Python中使用 + 运算符来拼接字符串可能会导致效率问题,因为Python中的字符串是不可变的,这意味着每次使用+运算符拼接字符串时,都会创建一个新的字符串对象,并将旧的字符串内容复制到新对象中。通常推荐使用str.join()方法,因为它只会在最后创建一个新字符串,避免了中间的多次复制。
4.9 * 实现字符串的复制
使用 * 可以实现字符串复制。
例:
a='Sxt'*3
print(a)
执行后:
'SxtSxtSxt'
4.10len()实现字符串的长度计算
len()用于计算字符串含有多少字符。
例:
d = 'abc'
print(len(d))
执行后:
3
4.11[]实现字符串的提取切片
字符串的本质就是字符序列,我们可以通过在字符串后面添加[],在[]里面指定偏移量,可以 提取/切片(slicing)指定位置的字符。
格式:
string[start:stop:step]
start: 切片开始的索引位置(包含)。如果省略,默认从字符串的起始位置开始。
stop: 切片结束的索引位置(不包含)。如果省略,默认到字符串的末尾。
step: 字符串中的步长,即每隔多少个字符取一个字符。如果省略,默认为1。
注意:
1.Python的索引是从0开始的
2.切片操作时,开始、结束的索引不在[0,字符串长度-1]这个范围,也不会报错。此时认为是从倒数开始切片,需要满足start < 0、stop < 0、start < stop
例:
s="Hello,Xworld!"
1.获取整个字符串:
print(s[:]) # 输出 "Hello,Xworld!"
2.从第3个字符到第7个字符:
print(s[2:7]) # 输出 "llo,X"
3.从开头到第5个字符:
print(s[:5]) # 输出 "Hello"
4.从第8个字符到最后:
print(s[7:]) # 输出 "world!"
5.从倒数第5个字符到倒数第3个字符:
print(s[-5:-2]) # 输出 "orl"
6.每隔一个字符取一个字符:
print(s[::2]) # 输出 "HloXol!"
7.反向输出整个字符串:
print(s[::-1]) # 输出 "!dlrowX,olleH"
4.12replace()实现字符串的替换
字符串是“不可改变”的,我们通过[]可以获取字符串指定位置的字符,但实际上我们没有改变字符串。我们尝试改变字符串中某个字符,会报错。但是,我们有时候确实需要替换某些字符。这时,只能通过str.replace创建新的字符串来实现。
格式:
str.replace(old, new, count)
返回一个字符串的拷贝,其中所有出现的old子字符串都被new子字符串所替换,可选参数count指定替换的最大次数。
例:
original_string = "aaabbbccc"
replaced_string = original_string.replace("bbb", "Python")
print(replaced_string)
replaced_string = original_string.replace("a", "A", 2)
print(replaced_string)
执行后:
aaaPythonccc
AAabbbccc
4.13split()和join()实现字符串的分割和拼接
str.split() 方法用于将一个字符串分割成列表,可以基于一个分隔符进行分割。如果没有指定分隔符,那么默认会根据空白字符(如空格、制表符、换行符等)进行分割。
格式:
str.split(sep, maxsplit)
sep:用于指定分隔符,默认为空白字符。
maxsplit:用于指定分割的最大次数,默认为 -1,表示不限制分割次数。
例:
text = "apple orange banana grape"
fruits = text.split() # 默认使用空白字符作为分隔符
print(fruits)
text = "one,two,three,four"
items = text.split(',', 2) # 使用逗号作为分隔符,最多分割两次
print(items)
执行后:
['apple', 'orange', 'banana', 'grape']
['one', 'two', 'three,four']
str.join() 方法用于将一个序列(如列表、元组等)中的元素连接成一个字符串,元素之间可以插入指定的分隔符。
格式:
sep.join(sequence)
sep:必需参数,用于指定连接元素之间的分隔符。
sequence:必需参数,用于指定待连接的序列。
例:
words = ['apple', 'orange', 'banana', 'grape']
sentence = ' '.join(words) # 使用空格作为分隔符
print(sentence)
numbers = [1, 2, 3, 4]
number_str = '-'.join(map(str, numbers)) # 使用短横线作为分隔符,注意需要将整数转换为字符串
print(number_str)
执行后:
apple orange banana grape
1-2-3-4
4.14字符串的比较和字符串的驻留机制
字符串的比较
字符串比较是确定两个字符串是否相等的过程。
1.基于内容的比较:比较 字符串的实际内容/两变量引用的对象的值 是否完全相同。这种比较通常使用==操作符或特定的字符串比较函数。
2.基于引用的比较:比较的是两个字符串变量是否引用内存中同一位置的对象。在Python中,is关键字就是用来比较引用的。
例:
s1 = "aa"
s2 = "bb"
print(s1+s2 == "aabb")
print(s1+s2 is "aabb")
执行后:
True
False
解释:
==操作符比较s1 + s2和字符串"aabb"时,实际上是在比较两个字符串的内容是否相同。在这种情况下,s1 + s2的结果确实是"aabb",所以==操作符返回True。
Is 操作符用于检查两个变量是否引用内存中的同一个对象。在本例中,s1 + s2和"aabb"虽然内容相同,但是它们在内存中可能是两个独立的对象。即使Python会对某些字符串字面量进行自动驻留,这种优化通常仅适用于在编译期就确定的字符串字面量。由于s1 + s2是在运行时动态创建的,它可能不会被驻留,因此与直接定义的字符串"aabb"在内存中位于不同的位置。因此,is操作符返回False。
字符串的驻留(String Interning)
字符串驻留是一种优化技术,用于减少内存中相同字符串副本的数量。当启用字符串驻留时,系统会维护一个字符串池,其中包含所有唯一的字符串字面量。如果尝试创建一个已经存在于池中的字符串,则不会创建新的实例,而是返回池中已有的字符串引用。
通过字符串的比较可以观察到字符串驻留的影响:
例:
s1 = "hello"
s2 = "hello"
s3 = "h" + "ello"
print(s1 is s2)
print(s1 is s3)
执行后:
True
True
解释:
s1 is s2输出 True,因为s1和s2引用相同的字符串对象。
s1 is s3输出 True,因为Python在编译期自动驻留了字符串"hello"。
4.15字符串常用方法汇总
常用查找方法
例:
a='''我是原神,今年 18 岁了,我在上海米哈游公司上班。我的儿子叫原洛希,他 6 岁了。我是一个编程教育的普及者,希望影响 8888 万学习编程的中国人。我儿子现在也开始学习编程,希望他 18 岁的时候可以超过我'''
方法和使用示例 | 说明 | 结果 |
'我是原神' in a | 判断某个字符(子字符串)是否在指定字符串中,not in正好相反 | True |
a.startswith('我是原神') | 判断是否是以指定字符串开头 | True |
a.endswith('过我') | 判断是否是以指定字符串结尾 | True |
a.find('原') | 查找并返回第一次出现指定字符串的索引 | 2 |
a.rfind('原') | 查找并返回最后一次出现指定字符串的索引 | 29 |
a.count("编程") | 统计并返回指定字符串出现的次数 | 3 |
a.isalnum() | 判断所有字符是否全是字母或数字 | False |
去除首尾信息
strip(), lstrip(), 和 rstrip() 方法用于去除字符串两端的指定字符如果不提供参数,均默认去除空白字符(包括空格、制表符、换行符等)。这些方法非常实用,特别是在处理用户输入或清理从文件读取的数据时。
方法和使用示例 | 说明 | 结果 |
text = " Hello, World! " text.strip() | 同时去除字符串两端的指定字符 | Hello, World! |
text = "--Hello, World!--" text.lstrip('-') | 去除字符串左侧(头部)的指定字符 | Hello, World!-- |
text = "--Hello, World!--" text.rstrip('-') | 去除字符串右侧(尾部)的指定字符 | --Hello, World! |
大小写转换
例:
a = "gao love programming, love SXT"
示例 | 说明 | 结果 |
a.capitalize() | 产生新的字符串,首字母大写 | 'Gao love programming, love sxt' |
a.title() | 产生新的字符串,每个单词都首字母大写 | 'Gao Love Programming, Love Sxt' |
a.upper() | 产生新的字符串,所有字符全转成大写 | 'GAO LOVE PROGRAMMING, LOVE SXT' |
a.lower() | 产生新的字符串,所有字符全转成小写 | 'gao love programming, love sxt' |
其他方法
1. isalnum() 是否为字母或数字
2. isalpha() 检测字符串是否只由字母组成(含汉字)。
3. isdigit() 检测字符串是否只由数字组成。
4. isspace() 检测是否为空白符
5. isupper() 是否为大写字母
6. islower() 是否为小写字母
4.16字符串的格式化
在Python中,字符串格式化是一种将变量或其他数据类型插入到字符串中的方法。
1. 使用百分号 % 的旧式字符串格式化
这是早期Python版本中常用的字符串格式化方法。它的工作原理类似于C语言中的printf风格的格式化。
例:
name = "Alice"
age = 30
print("Hello, %s! You are %d years old." % (name, age))
执行后:
Hello, Alice! You are 30 years old.
2. 使用 str.format() 方法
str.format() 方法是在Python 2.6中引入的,提供了一种更现代、更灵活的方式来格式化字符串。
例:
name = "Alice"
age = 30
add = 10
# 直接使用.format()
print("Hello, {}! You are {} years old.".format(name, age))
# 可以在{}中直接嵌入表达式
print("Hello, {}! You are {} years old.".format(name, age+add))
# 可以使用形参指定
print("Hello, {name}! You are {age} years old.".format(name=name, age=age))
# 可以使用占位符
print("Hello, {0}! You are {1} years old.".format(name, age))
执行后:
Hello, Alice! You are 30 years old.
Hello, Alice! You are 30 years old.
Hello, Alice! You are 40 years old.
Hello, Alice! You are 30 years old.
3. 使用 f-string(格式化字符串文字)
f-string 是在Python 3.6中引入的一种新特性,它提供了一种更简洁、更易读的字符串格式化方式。
例:
name = "Alice"
age = 30
print(f"Hello, {name}! You are {age} years old.")
执行后:
Hello, Alice! You are 30 years old.
4.17字符串的填充和对齐
在Python中,字符串的填充与对齐是指在字符串的左侧、右侧或两侧添加额外的字符,以达到某种视觉上的效果或满足特定的格式要求,填充常跟对齐一起使用。
1. 使用字符串的ljust()、rjust()、center()方法
ljust(width[, fillchar]):左对齐,返回一个原字符串左对齐,并使用fillchar(默认空格)填充至长度为width的新字符串。
rjust(width[, fillchar]):右对齐,返回一个原字符串右对齐,并使用fillchar(默认空格)填充至长度为width的新字符串。
center(width[, fillchar]):居中对齐,返回一个原字符串居中,并使用fillchar(默认空格)填充至长度为width的新字符串。
例:
text = "hello"
print(text.ljust(10,'*'))
print(text.rjust(10))
print(text.center(10,'x'))
执行后:
hello*****
hello
xxhelloxxx
2. 使用 str.format() 方法
“^ < >”表示对齐方式:居中、左对齐、右对齐,后面带宽度
“:”表示填充,后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充
例:
text = "hello"
print("{:*<10}".format(text))
print("{text:>10}".format(text=text))
print("{:x^10}".format(text))
执行后:
hello*****
hello
xxhelloxxx
3. 使用 f-string
“^ < >”表示对齐方式:居中、左对齐、右对齐,后面带宽度
“:”表示填充,后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充
例:
text = "hello"
print(f"{text:*<10}")
print(f"{text:>10}")
print(f"{text:x^10}")
执行后:
hello*****
hello
xxhelloxxx
4.18可变字符串
由于Python中的字符串是不可变对象,你不能像修改列表那样直接修改字符串中的某个字符。但是,如果你需要“原地”修改字符串,或者更准确地说,需要高效地构建或修改字符串,可以使用一些替代方案,如使用io.StringIO或array.array。不过,更常见的做法是使用列表(list)来达到类似的效果,因为列表是可变的。
1. 使用列表(List)
由于列表是可变的,你可以先将字符串转换为列表,进行修改,然后再转换回字符串。这是最简单且常用的方法。
例:
s = list("Hello World")
s[0] = 'h' # 修改第一个字符为小写 h
s = ' '.join(s) # 将列表转换回字符串
print(s)
执行后:
hello World
2. 使用 io.StringIO
io.StringIO 类似于一个内存中的文件对象,可以用来读写字符串。虽然它本身不支持原地修改字符串,但它提供了一个方便的方式来构建或编辑字符串,尤其适合处理大量字符串数据。
例:
from io import StringIO
# 创建一个StringIO对象并初始化为"Hello World\n"
s = StringIO("Hello World\n")
# 读取所有内容
content = s.getvalue()
# 修改内容(将"Hello"改为"hello")
new_content = content.replace("Hello", "hello")
# 清空StringIO对象
s.seek(0)
s.truncate(0)
# 将修改后的内容写回StringIO对象
s.write(new_content)
# 现在你可以再次获取修改后的内容
modified_content = s.getvalue()
print(modified_content) # 输出:hello World
执行后:
hello World
3. 使用 array.array
array.array 是一个存储单一类型数据的数组,可以用来存储字符串中的字符(使用'c'或'u'类型码)。但是,使用array.array来处理字符串可能比使用列表或io.StringIO更复杂,且在大多数情况下并不是最直观的选择。
例:
import array
a = array.array('u', 'Hello World')
a[0] = 'h' # 修改第一个字符
print(' '.join(a))
执行后:
hello World