字符串str
字符串是字符的容器:一个字符串可以存放任意数量的字符(包含零个或者多个字符的有序不可变序列)。
需要注意:
- 不可变:内容一旦确定,就不允许发生变化
- 有序: 添加顺序和显式顺序一致,元素在添加的时候会为元素设置编号,这个编号是从0开始的【这个编号称为索引、下标、脚标】
- 序列是指:内容连续、有序,可使用下标索引的一类数据容器。列表、元组、字符串,均可以可以视为序列。
1. 字符串的定义
有两种方式来进行定义:
- 使用引号包含格式的字面量定义法
- 使用
str()
进行构造
# 空字字符串
str0 = ''
str0_0 = str()
# 创建字符串
str1 = "我是字符串"
str2 = str("我是字符串")
#str() 不仅可以创建字符串,而且可以将赋值参数转换为字符串类型
str3 = str(10) # "10"
str4 = str([1,2,3,4]) #"[1,2,3,4]"
字符串的分类:
转义字符串:因为在编程语言中有
\
,是转义符,会将一些特殊的符号转义成其他的含义n ----> \n 换行符 t ----> \t 水平制表符 r ----> \r 回车符 【windows系统的字节模式下 换行符是两个符号组成的 \r\n】 f ----> \f 换页符 v ----> \v 纵向制表符 u ----> \u unicode码的前缀 '\u4e00' x ----> \x 字节模式下 十六进制的前缀
原生字符串:保持每个字符原本的含义,就是原生字符串
对比一下:
\n
在转义字符串中是 一个换行符, 原生字符串解读,应该是两个符号反斜杠和n
将转义字符串转化成原生字符串的方式:
- 使用
\
进行再次转义使用
r
或者R
修饰字符串
s = 'C:\\Users\jkMaster\Documents\\test.txt'
print(s)
s = r'C:\Users\jkMaster\Documents\test.txt'
print(s)
# 这两字符串变量打印结果时一样,但是不同点在于,当遇到python中的转移字符串时,如何将转移字符串转变会原有含义的操作即原生字符串的操作
2. 运算符的相关操作
# +号运算符 提供的是拼接操作(要求:字符串只能和字符串拼接)
print("hello"+" world")
# *号运算符 乘以一个正整数n 将字符串的内容重复n次
print("qfedu "*3)
# %号运算符 格式化在字符串未知的位置使用占位符占位,再对字符串使用%运算符给占位符赋值
# %s字符串 %d整数 %f小数
print("姓名:%s,年龄%d,薪水%.2f"%("张三",18,1234.56))
# +=号运算符 在变量原来值的基础上拼接上新的内容(要求:字符串只能和字符串拼接)
str1 = "hello"
str1 += " world"
print(str1)
# *=号运算符 在变量值的基础上将内容重复n次 赋值给变量
str2 = "qfedu "
str2 *= 3
print(str2)
# 关系运算符 > >= < <= == !=
# 字符在比较的时候按照什么来比较的??? python是utf-8的编码 所以它是按照utf-8编码规则 对比字符对应的十进制数据
str3_1 = "a"
str3_2 = "A"
print(str3_1 > str3_2)
# 成员运算符
str4_1 = "a"
str4_2 = "abc"
print(f"a是否存在abc中?{str4_1 in str4_2}")
print(f"a是否不存在abc中?{str4_1 not in str4_2}")
#身份运算符
str5_1 = "abc"
str5_2 = "abc"
print(f"str5_1中存储的字符串内存地址是:{id(str5_1)}")
print(f"str5_2中存储的字符串内存地址是:{id(str5_2)}")
print(f"str5_1和str5_2的地址是否相等?:{str5_1 is str5_2}")
print(f"str5_1和str5_2的地址是否不相等?:{not str5_1 is str5_2}")
3. 索引和切片
3.1. 索引
索引就是表名字符串中存储字符对应的位置
Python对于序列的索引有两种方式的操作:
正向索引 【从左向右数】范围是[0, 长度N-1]
负向索引 【从右向左数】范围是[-1, -N, -1] — 递减数列
对于有序序列来说,想要定位获取或者修改序列中的元素,就需要索引来进行定位,格式:
序列[索引]
# len(序列) --》可以获取序列的长度
s = '\n'
print(len(s)) # 1
s1 = r'\n'
print(len(s1)) # 2
s = r'Welcome to qfedu study'
print(len(s)) # 22
# 获取第一个字符
ch = s[0] # 定位到之后赋值给变量
print(ch) # W
# 负向索引
ch = s[-len(s)]
print(ch) # W
# 获取最后一个字符
last_ch = s[len(s) - 1]
print(last_ch) # y
last_ch = s[-1]
print(last_ch) # y
# 获取倒数第三个字符
last_ch_3 = s[-3]
print(last_ch_3)
# 字符串是不允许发生变化【不可变】
# s[0] = 'w' # 修改这个位置的元素
# TypeError: 'str' object does not support item assignment
# 类型错误:字符串对象不支持元素被指派内容
3.2. 切片
切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。
通过索引定位范围区域,在这个区域中提取相关的子串信息,切片的操作是
序列[起始索引:结束索引:步长]
起始索引和结束索引只是定位范围的,使用正向索引和负向索引均可
根据步长的正负情况切片是分为两种的
正向切片 【从左向右提取子串】
步长是为正数,起始索引定位的字符应该在结束索引定位的左边
从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置
负向切片 【从右向左提取子串】
步长是负数,起始索引定位的字符应该在结束索引定位的右边
从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置
切片的操作中有些内容是可以省略的:
:步长
可以省略,表示步长为1起始索引
可以省略,如果是正向切片 表示从最左边开始, 如果是负向切片 表示从最右边开始结束索引
可以省略,如果是正向切片 表示到最右边结束,如果是负向切片 表示到最左边结束
s = r'Welcome to qfedu study'
sub_s = s[0:len(s):1]
print(sub_s) # Welcome to qfedu study
# 等价于
sub_s = s[:]
print(sub_s) # Welcome to qfedu study
sub_s = s[-1:-len(s)-1:-1]
print(sub_s) # 对字符串反转
# yduts udefq ot emocleW
# 等价于
sub_s = s[::-1]
print(sub_s)
# tyduts udefq ot emocleW
sub_s = s[:3] # 提取前3个
print(sub_s) # Wel
sub_s = s[-3:] # 提取的是后3个字符
print(sub_s) # udy
sub_s = s[-3::-1]
print(sub_s) # uts udefq ot emocleW
sub_s = s[1:-1:-1]
print(sub_s) # ''
sub_s = s[::2]
print(sub_s) # Wloet fd td
4. 字符串遍历
方式1:直接遍历获取元素
for 变量名 in 字符串: 操作
方式2:使用range生成下标数列,根据下标获取元素
for 变量名 in range(len(字符串)): 操作
方式3:enumerate枚举遍历序列
对序列操作完成时候 会生成一个新的序列,这个序列中的元素是一个二元组
(下标, 元素)
s = 'nice hello'
for ch in s:
print(ch)
'''
n
i
c
e
'''
print('=' * 30)
# 因为字符串是有序序列 可以通过索引获取元素
for i in range(len(s)):
print(i, s[i])
# 获取e这个字符在字符串中的位置
# 直接遍历下标
for i1 in range(len(s)):
if s[i1] == 'e':
print(i1)
# enumerate(s) ---> [(下标, 元素), (下标1, 元素1), (下标2, 元素2)] --》元组的操作在后面会详细说明 这里大家知道如何操作即可
for item in enumerate(s):
print(item)
'''
(0, 'n')
(1, 'i')
(2, 'c')
(3, 'e')
(4, ' ')
(5, 'h')
(6, 'e')
(7, 'l')
(8, 'l')
(9, 'o')
'''
# 解包: 给多个变量赋值的时候
x, y, z = 10, 11, 12
print(x, y, z) # 10 11 12
'''
当用逗号分割定义数据时, 解释器会将其解释为一个元组类型
'''
data = 1, 2, 3, 4, 5, 6 # 打包
print(data, type(data)) # (1, 2, 3, 4, 5, 6) <class 'tuple'>
'''
当把多个数据赋值给多个变量时, 是在给元组数据解包, 将数据赋值给对等位置的变量
'''
for pos, ele in enumerate(s):
if ele == 'e':
print(pos)
5. 字符串的相关操作
5.1. 获取的操作 【重要】
s = r'Welcome to qfedu study'
'''
1. 在指定范围中 查询子串第一次出现的位置
字符串对象.index(子串, 起始位置, 结束位置) --- 找不到报错
字符串对象.find(子串, 起始位置, 结束位置) --- 找不到 返回的是-1
子串是多个符号 获取的是第一个符号的下标
'''
# 不规定查找范围 从左到右整体查询
pos = s.index('s')
print(pos)
# 对'也有转义的意思 在字符串要展示的内容中 要呈现 '
# 王籽澎的昵称是 '隔壁老王'
message = '王籽澎的昵称是 \'隔壁老王\''
print(message)
# 从指定位置开始进行查找
pos = s.index('s', 3)
print(pos)
# 指定开始与结束[不包含]
#pos = s.index('s', 3, 8)
# print(pos) # ValueError: substring not found
s1 = 'noodle too'
pos = s1.index('oo')
print(pos) # 1
pos = s.find('s', 3, 8)
print(pos) # -1
'''
2. 在指定范围中 查询子串最后一次出现的位置
字符串对象.rindex(子串, 起始位置, 结束位置) --- 找不到报错
字符串对象.rfind(子串, 起始位置, 结束位置) --- 找不到 返回的是-1
子串是多个符号 获取的是第一个符号的下标
'''
pos = s.rfind('s')
print(pos) # 17
pos = s.rfind('s', 0, 10)
print(pos) # -1
'''
3. 在指定范围中 查询子串出现的次数
字符串对象.count(子串, 起始位置, 结束位置)
'''
pos = s.count('s')
print(pos) # 1
# 指定起始 到末尾开始查找
pos = s.count('s', 8)
print(pos) # 1
pos = s.count('s', 8, len(s))
print(pos) # 1
5.2. 转换的操作 【重要】
s = 'helLo,Nice to Meet you.My age is 18.aheklfnfsd hjdhsjhgfs '
# 1. 将小写英文字母转化为大写 其他的不变
new_s = s.upper()
print(new_s) # HELLO,NICE TO MEET YOU.MY AGE IS 18.
print(s)
# 2. 将大写英文字母转化为小写 其他的不变
new_s = s.lower()
print(new_s) # hello,nice to meet you.my age is 18.
# 3. 大写转小写 小写转大写 其他字符不变
new_s = s.swapcase()
print(new_s) # HELLO,nICE TO mEET YOU.mY AGE IS 18.
# 4. 首字母大写 其他字母小写 其他符号不变
new_s = s.capitalize()
print(new_s) # Hello,nice to meet you.my age is 18.
# 5. 每个单词首字母大写 其他小写
# 单词: 非连续性的符号组在一起就是单词
new_s = s.title()
print(new_s) # Hello,Nice To Meet You.My Age Is 18.Aheklfnfsd Hjdhsjhgfs
# 6. 根据编码规则 获取字符对应的字节数据
print(hex(255)) # 0xff
'''
GBK编码 一个汉字2个字节 1个字节是8位
UTF-8编码 一个汉字是3个字节
二进制数据位数比较多 可读性差一些 所以展示字节数据的时候 使用的十六进制的格式
单字节数据 【ASCII】 --- 编码之前和编码之后的形态是一样的
'''
s = 'abc1234你好'
# 按照GBK的编码规则 获取字符对应的字节数据
byte_data = s.encode(encoding='gbk')
print(byte_data) # b'abc1234\xc4\xe3\xba\xc3' 字节串
# 字节串的内容就是 字节数据 [呈现的时候转化为十进制数据了]
for b in byte_data:
print(b)
'''
97
98
99
49
50
51
52
196
227
186
195
'''
# 解码: 将字节数据按照编码规则 解析成字符串
s1 = byte_data.decode(encoding='gbk') # 编码规则和解码规则要保持一致 如果不一致 要么报错 要么乱码
print(s1) # abc1234你好
s2 = '你好啊'
byte_data1 = s2.encode(encoding='utf-8')
print(byte_data1) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x95\x8a'
# s3 = byte_data1.decode(encoding='gbk')
# print(s3) # UnicodeDecodeError: 'gbk' codec can't decode byte 0x8a in position 8: incomplete multibyte sequence
s4 = '你好'
byte_data2 = s4.encode(encoding='utf-8')
print(byte_data2) # b'\xe4\xbd\xa0\xe5\xa5\xbd'
s5 = byte_data2.decode(encoding='gbk')
print(s5) # 浣犲ソ
5.3. 判断的操作 【重要】
# 1. 判断字符串的内容是否为纯数字
s = '1230'
res = s.isdigit()
print(res) # True
s = '1230 '
print(s.isdigit()) # False
# 2. 判断字符串的内容是否为纯字母
# 字母:世界各国语言 统称为字母
s = 'abc你Вㅘタ'
res = s.isalpha()
print(res) # True
# 要判断是否为纯英文字母 【英文是单字节数据特点】
'''
单字节和多字节的特点是编码之后 的字节串的内容不一样
单字节保持不变 【不会出现其他的符号】
多字节会按照字节数转成十六进制的数据 【例如\xaf】 就会出现非字母的符号
'''
s1 = 'abc'
s2 = 'abc你'
print(s1.encode(encoding='utf-8')) # b'abc'
print(s2.encode(encoding='utf-8')) # b'abc\xe4\xbd\xa0'
# 要判断是否为纯英文字母
print(s1.encode('utf-8').isalpha()) # True
print(s2.encode('utf-8').isalpha()) # False
# 3. 判断字符串的内容是否为数字或者字母 [纯数字 纯字母 数字和字母]
print('123'.isalnum()) # True
print('123abc'.isalnum()) # True
print('123abc比你好'.isalnum()) # True
print('123abc你好 hello'.isalnum()) # False
# 如何判断字符串的内容为数字或者英文字母 【同上】
print('123abc'.encode(encoding='utf-8').isalnum()) # True
print('123abc比你好'.encode(encoding='utf-8').isalnum()) # False
# 如何判断字符串的内容为数字和英文字母 【既有数字 又有英文字母】
s = '123'
res = s.encode(encoding='utf-8').isalnum() is True and s.isdigit() is False and s.encode(encoding='utf-8').isalpha() is False
print(res)
# 4. 判断字符串中的英文字母是否为大写字母
s = 'her12324'
res = s.isupper()
print(res) # False
s1 = 'HER12324'
res = s1.isupper()
print(res) # True
# 5. 判断字符串中的英文字母是否为小写字母
res = s.islower()
print(res) # True
res = s1.islower()
print(res) # False
# 6. 判断字符串的内容是否满足 单词的首字母大写 其他小写
s = 'Good Nice 13'
res = s.istitle()
print(res) # True
s1 = 'Good nice 13'
res = s1.istitle()
print(res) # False
# 7. 判断字符串的内容是否是ASCII码符号
print(s.isascii()) # True
# 8. 判断字符串的内容是否已指定内容开头
# res = 'good good study'.startswith(指定内容)
'''
指定内容的数据类型:
1. 字符串 验证是否以指定的字符串开头
2. (字符串1,字符串2, 字符串3) 元组类型的数据 判断字符串的内容是否以其中一个开头
'''
res = 'good good study'.startswith('good')
print(res) # True
res = 'Good good study'.startswith('good')
print(res) # False
res = 'Good good study'.startswith(('good', 'Good', 'GOOD'))
print(res) # True
# 9. 判断字符串的内容是否已指定内容结尾
'''
1. 字符串 验证是否以指定的字符串结尾
2. (字符串1,字符串2, 字符串3) 元组类型的数据 判断字符串的内容是否以其中一个结尾
'''
res = 'good good study'.endswith('dy')
print(res)
res = 'good good stuDy'.endswith(('dy', 'Dy', 'DY', 'dY'))
print(res)
5.4. 格式化的操作
# 1. 按照指定宽度 对展示的字符串内容填充数据 【居左右填充 居右左填充 居中左右填充】
s = 'hello'
print(s)
# 居左右填充
# new_s = s.ljust(宽度, 填充符) # 填充符默认是空格
new_s = s.ljust(10)
print(new_s) # 'hello '
new_s = s.ljust(10, '-')
print(new_s) # hello-----
# 居右左填充
new_s = s.rjust(10)
print(new_s) # ' hello'
new_s = s.rjust(10, '*')
print(new_s) # '*****hello'
# 居中
new_s = s.center(10)
print(new_s) # ' hello '
new_s = s.center(10, '+')
print(new_s) # '++hello+++'
# 2. 按照指定宽度 对字符串进行右对齐 左边填充0
s = '10'
new_s = s.zfill(10)
print(new_s) # 0000000010
# 3. 引号嵌套的问题*** 【展示的内容中有双引号 字符串数据就采用单引号包含 】
# 展示的内容中有单引号 字符串数据就采用双引号包含
s = "王籽澎的昵称是 '隔壁老王'"
print(s)
s = '王籽澎的昵称是 "隔壁老王"'
print(s)
# 有冲突的情况 内外引号情况一样 解决方式就是对内部引号采用转义符转义 取消掉字符串标记的含义
s = '王籽澎的昵称是 \'隔壁老王\''
print(s)
# 4. 字符串内容比较长 *** 可以直接换行写多个字符串 会自动拼接在一起 使用\把多个字符串连接在一起 形成一个
s = '其中五六只虾已熟透发红。方女士称,当天气温41度,' \
'可能是自己把虾往地上和电动车后座放了的缘故,温度太高虾被烫熟了,' \
'觉得十分搞笑。感慨这天气能不出门就不出门,待在空调房里最香。'
print(s)
s = '其中五六只虾已熟透发红。方女士称,当天气温41度,可能是自己把虾往地上和电动车后座放了的缘故,温度太高虾被烫熟了,觉得十分搞笑。感慨这天气能不出门就不出门,待在空调房里最香。'
print(s)
# 5. 字符串格式化
'''
除了%运算符之外 字符串也提供了相应的操作
字符串对象.format(填充的数据)
这种格式化方式,字符串对象里面的未知数据的占位符采用的是{}
'''
name = '王籽澎'
gender = '男'
age = 21
score = 79.9
message = '这个人叫%s, 今年%d岁 性别是%s 成绩是%f' % (name, age, gender, score)
print(message)
message = '这个人叫{}, 今年{}岁 性别是{} 成绩是{:.2f}'.format(name, age, gender, score)
print(message)
''' *******
Python3.6出现了简化操作 使用f或者F修饰字符串 在需要填充数据的地方 直接 {数据}
如何对数据进一步格式化
保留多少位小数 {数据:.nf} n保留小数的位数
按照指定宽度填充数据 {数据:[占位符][对齐模式][宽度]}
占位符默认是空格
对齐模式 >[居右] ^[居中] <[居左]
千位分割法 {数据:,}
'''
message = f'这个人叫{name}, 今年{age}岁 性别是{gender} 成绩是{score:.2f} 学号{10:0>6} 千位分割{12345678987654567:,}' \
f'二进制展示数据{10:0b} 八进制展示数据{10:0o} 十六进制{10:0x} ' \
f'科学计数法{123456789234567:e}'
print(message)
value = input('请输入数据:')
# 打印出来的信息是 value=数据值
info = f'{value=}' # 3.8中新增的
print(info) # value='19'
5.5. 切割和拼接
# 切割: 以指定子串为切割点 将字符串分成n段
'''
字符串数据.split(切割符, 切割次数) 没有设置切割次数 能切几次切几次
从左开始查找切割点 进行切割的
字符串数据.rsplit(切割符, 切割次数) 没有设置切割次数 能切几次切几次
从右开始查找切割点 进行切割的
'''
s = 'hello nice to meet you'
# 以 'e'为切割点
sub_list = s.split('e')
print(sub_list) # ['h', 'llo nic', ' to m', '', 't you']
'''
'h'
'llo nic'
' to m'
''
't you'
'''
# 如果没有设置切割符 默认以任意的空白符号为切割符 会将结果中的空字符串给移除
'''
空格
换行
制表符等等
'''
sub_list = s.split()
print(sub_list) # ['hello', 'nice', 'to', 'meet', 'you']
# 设置切割次数
sub_list = s.split('e', 1)
print(sub_list) # ['h', 'llo nice to meet you']
sub_list = s.rsplit('e')
print(sub_list) # ['h', 'llo nic', ' to m', '', 't you']
sub_list = s.rsplit('e', 1)
print(sub_list) # ['hello nice to me', 't you']
# 2. 拼接
# 使用拼接符把序列中的内容拼接成一个字符串
'''
'拼接符'.join(序列)
底层实现就是采用的+号拼接 【字符串只能跟字符串拼接】
序列中的元素必须是字符串类型的
'''
words = ['hello', 'nice', 'to', 'meet', 'you']
res = '_'.join(words)
print(res) # hello_nice_to_meet_you
# nums = (11, 23, 45)
# res = '+'.join(nums) # TypeError: sequence item 0: expected str instance, int found
5.6. 替换和移除
# 替换
'''
字符串数据.replace(旧子串, 新子串, 个数)
旧子串 --- 要替换掉的
新子串 --- 要替换成的
个数 --- 不设置的换 默认全部替换
'''
s = 'good good god'
new_s = s.replace('g', 'G')
print(new_s) # Good Good God
new_s = s.replace('g', 'G', 1)
print(new_s) # Good good god
new_s = s.replace(' ', '_')
print(new_s) # good_good_god
'''
移除的是两端的内容
字符串数据.strip(指定内容) 移除字符串两端的指定内容
字符串数据.lstrip(指定内容) 只移除左端的指定内容
字符串数据.rstrip(指定内容) 只移除右端的指定内容
指定内容没有设置 移除的是任意的空白符号
'''
s = ' \t\r\nabc\tgood \n'
new_s= s.strip()
print(new_s) # abc good
s = '@#$%^abc\tgood^%$#'
new_s = s.strip('@#$%^&*') # 左右逐个获取 验证是否在指定的内容中 在的话移除 不在话停止移除操作
print(new_s) # abc good
s = '@#$%^abc\tgood^%$#'
new_s = s.lstrip('@#$%^&*') # 左右逐个获取 验证是否在指定的内容中 在的话移除 不在话停止移除操作
print(new_s) # abc good^%$#
s = '@#$%^abc\tgood^%$#'
new_s = s.rstrip('@#$%^&*') # 左右逐个获取 验证是否在指定的内容中 在的话移除 不在话停止移除操作
print(new_s) # @#$%^abc good
总结:
作为数据容器,字符串有如下特点:只可以存储字符串、长度任意(取决于内存大小)、支持下标索引、允许重复字符串存在、不可以修改(增加或删除元素等)、支持for循环