第五章 Python数据容器 02-str容器

字符串str

字符串是字符的容器:一个字符串可以存放任意数量的字符(包含零个或者多个字符的有序不可变序列)。

需要注意:

  • 不可变:内容一旦确定,就不允许发生变化
  • 有序: 添加顺序和显式顺序一致,元素在添加的时候会为元素设置编号,这个编号是从0开始的【这个编号称为索引、下标、脚标
  • 序列是指:内容连续、有序,可使用下标索引的一类数据容器。列表、元组、字符串,均可以可以视为序列。

1. 字符串的定义

有两种方式来进行定义:

  1. 使用引号包含格式的字面量定义法
  2. 使用str()进行构造
# 空字字符串
str0 = ''
str0_0 = str()

# 创建字符串
str1 = "我是字符串"
str2 = str("我是字符串")

#str() 不仅可以创建字符串,而且可以将赋值参数转换为字符串类型
str3 = str(10) # "10"
str4 = str([1,2,3,4]) #"[1,2,3,4]"

字符串的分类:

  1. 转义字符串:因为在编程语言中有\,是转义符,会将一些特殊的符号转义成其他的含义

    n ----> \n  换行符
    t ----> \t  水平制表符
    r ----> \r  回车符  【windows系统的字节模式下  换行符是两个符号组成的  \r\n】
    f ----> \f  换页符
    v ----> \v  纵向制表符
    u ----> \u  unicode码的前缀   '\u4e00'
    x ----> \x  字节模式下 十六进制的前缀
    
  2. 原生字符串:保持每个字符原本的含义,就是原生字符串

    对比一下:\n 在转义字符串中是 一个换行符, 原生字符串解读,应该是两个符号反斜杠和n

    将转义字符串转化成原生字符串的方式:

    1. 使用\进行再次转义
  3. 使用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对于序列的索引有两种方式的操作:

  1. 正向索引 【从左向右数】范围是[0, 长度N-1]

  2. 负向索引 【从右向左数】范围是[-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. 正向切片 【从左向右提取子串】

    步长是为正数,起始索引定位的字符应该在结束索引定位的左边

    从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置

  2. 负向切片 【从右向左提取子串】

    步长是负数,起始索引定位的字符应该在结束索引定位的右边

    从起始索引定位的字符开始 按照步长 获取相应的字符,注意不包含结束索引对应的位置

切片的操作中有些内容是可以省略的:

  1. :步长可以省略,表示步长为1
  2. 起始索引可以省略,如果是正向切片 表示从最左边开始, 如果是负向切片 表示从最右边开始
  3. 结束索引可以省略,如果是正向切片 表示到最右边结束,如果是负向切片 表示到最左边结束
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循环

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值