Python的字符串和字节型
⽬录
字符串(str)
字符串的定义
字符串就是⼀串字符,是编程语⾔中表⽰⽂本的数据类型
在 Python 中可以使⽤⼀对双引号 " 或者⼀对单引号 ' 定义⼀个字符串
可以使⽤索引获取⼀个字符串中指定位置的字符,索引计数从 0 开始
也可以使⽤ for 循环遍历字符串中每⼀个字符
#!/usr/bin/env python3
# -*-coding:utf-8-*-
"""
@author:fyh
@time:2019/5/31
"""
str1 = "hello python"
for c in str1:
print(c, end='\t')
# 运⾏结果:h e l l o p y t h o n
字符串的常⽤操作
#!/usr/bin/env python3
# -*-coding:utf-8-*-
"""
@author:fyh
@time:2019/5/31
"""
# 1 * 重复输出字符串
print('hello' * 2)
# 2 [] ,[:] 通过索引获取字符串中字符
print('helloworld'[2:])
# 3 in 成员运算符 - 如果字符串中包含给定的字符返回 True
print('el' in 'hello')
# 4 % 格式字符串
print('alex is a good teacher')
print('%s is a good teacher' % 'alex')
# 5 + 字符串拼接
a = '123'
b = 'abc'
c = '789'
d1 = a + b + c
print(d1) # +效率低,该⽤join
# join效率⾼
d2 = ''.join([a, b, c])
print(d2)
字符串相关的函数
常⽤函数
# string.upper() 转换 string 中的⼩写字母为⼤写
# string.lower() 转换 string 中所有⼤写字符为⼩写
# string.startswith(obj, beg=0,end=len(string)) 检查字符串是否是以obj开头,是则返回True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
# dswith(obj, beg=0, end=len(string)) 检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False. # place(str1, str2, unt(str1)) 把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
# string.strip([obj]) 在 string 上执⾏ lstrip()和 rstrip() 去除空格
# string.split(str="", unt(str)) 以 str 为分隔符切⽚ string,如果 num有指定值,则仅分隔 num 个⼦字符串
# string.find(str, beg=0, end=len(string)) 检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1 # de(encoding='UTF-8',
errors='strict') 以 encoding 指定的编码格式编码 string,如果出错默认报⼀个ValueError 的异常,除⾮ errors 指定的是ignore或者replace
# string.decode(encoding='UTF-8', errors='strict') 以 encoding 指定的编码格式解码 string,如果出错默认报⼀个ValueError的异常,除⾮errors指定的是'ignore'或者'replace'
# string.join(seq) 以 string 作为分隔符,将 seq 中所有的元素(的字符串表⽰)合并为⼀个新的字符串
# string.format() 格式化输出
其它函数
# string.capitalize() 把字符串的第⼀个字符⼤写
# (width) 返回⼀个原字符串居中,并使⽤空格填充⾄长度 width 的新字符串
# unt(str, beg=0, end=len(string)) 返回 str 在 string ⾥⾯出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数
# pandtabs(tabsize=8) 把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是8。
# string.index(str, beg=0, end=len(string)) 跟find()⽅法⼀样,只不过如果str不在 string中会报⼀个异常.
# string.isalnum() 如果 string ⾄少有⼀个字符并且所有字符都是字母或数字则返回 True,否则返回 False
# string.isalpha() 如果 string ⾄少有⼀个字符并且所有字符都是字母则返回 True,否则返回 False
# string.isdecimal() 如果 string 只包含⼗进制数字则返回 True 否则返回 False.
# string.isdigit() 如果 string 只包含数字则返回 True 否则返回 False.
# string.islower() 如果 string 中包含⾄少⼀个区分⼤⼩写的字符,并且所有这些(区分⼤⼩写的)字符都是⼩写,则返回 True,否则返回 False
# string.isnumeric() 如果 string 中只包含数字字符,则返回 True,否则返回 False
# string.isspace() 如果 string 中只包含空格,则返回 True,否则返回 False.
# string.istitle() 如果 string 是标题化的(见 title())则返回 True,否则返回 False
# string.isupper() 如果 string 中包含⾄少⼀个区分⼤⼩写的字符,并且所有这些(区分⼤⼩写的)字符都是
⼤写,则返回 True,否则返回 False
# string.ljust(width) 返回⼀个原字符串左对齐,并使⽤空格填充⾄长度 width 的新字符串
# string.lstrip() 截掉 string 左边的空格
# string.maketrans(intab, outtab]) maketrans() ⽅法⽤于创建字符映射的转换表,对于接受两个参数的最简单的调⽤⽅式,第⼀个参数是字符串,表⽰需要转换的字符,第⼆个参数也是字符串表⽰转换的⽬标。# max(str) 返回字符串 str 中最⼤的字母。
# min(str) 返回字符串 str 中最⼩的字母。
# string.partition(str) 有点像 find()和 split()的结合体,从 str 出现的第⼀个位置起,把字符串 string 分成⼀个 3 元素的元组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string. # string.rfind(str, beg=0,end=len(string) ) 类似于 find()函数,不过是从右边开始查.
# string.rindex( str, beg=0,end=len(string)) 类似于 index(),不过是从右边开始.
# string.rjust(width) 返回⼀个原字符串右对齐,并使⽤空格填充⾄长度 width 的新字符串
# string.rpartition(str) 类似于 partition()函数,不过是从右边开始查.
# string.rstrip() 删除 string 字符串末尾的空格.
# string.splitlines(unt('\n')) 按照⾏分隔,返回⼀个包含各⾏作为元素的列表,如果 num 指定则仅切⽚ num 个⾏.
# string.swapcase() 翻转 string 中的⼤⼩写
# string.title() 返回"标题化"的 string,就是说所有单词都是以⼤写开始,其余字母均为⼩写(见 istitle())
# anslate(str, del="") 根据 str 给出的表(包含 256 个字符)转换 string 的字符,要过滤掉的字符放到 del 参数中
案例:
#!/usr/bin/env python3
# -*-coding:utf-8-*-
"""
@author:fyh
@time:2019/5/31
"""
name = "hello world"
# ⼩写字母变为⼤写
print(name.upper()) # HELLO WORLD
print(name) # hello world
# 把⼤写字母变⼩写
name2 = "HELLO WORLD"
print(name2.lower()) # hello world
print(name2) # HELLO WORLD
# 判断是否以。。。开头
name3 = "hello"
print(name3.startswith("he")) # True
# 检查字符串是否以。。结尾
dswith("lo")) # True
# replace 替换
name4 = "python"
place('th', 'aa')) # pyaaon
# 去除空格
name5 = " bbcc "
print(name5.strip()) # bbcc
# 分割
str1 = "aa|bb|cc|dd"
print(str1.split('|')) # ['aa', 'bb', 'cc', 'dd']
# 查返回开始的索引值
str2 = "we are family"
print(str2.find("are")) # 3
# join 拼接
lst1 = ['aa', 'bb', 'cc', 'dd']
print("-".join(lst1)) # aa-bb-cc-dd
字符串切⽚
切⽚使⽤索引值来限定范围,根据步长从原序列中取出⼀部分元素组成新序列
切⽚⽅法适⽤于字符串、列表、元组
切⽚的语法表达式为:[start_index : end_index : step],其中:
start_index:起始索引
end_index:结束索引
step:步长
切⽚操作是指按照步长,截取从起始索引到结束索引,但不包含结束索引(也就是结束索引减1)的所有元素。
切⽚不会改变原对象,⽽是重新⽣成了⼀个新的对象
#!/usr/bin/env python3
# -*-coding:utf-8-*-
"""
@author:fyh
@time:2019/5/31
"""
str1 = "hello world"
print(str1[1:6])
# 结果是ello
print(str1[1:6:2])
# 结果是el
print(str1[2:])
# 结果是llo world
# 保留start_index,但省略end_index,这样会从起始索引开始,切到最后⼀个元素为⽌
print(str1[:5])
# 结果是hello
# 省略start_index,保留end_index,这样会从第⼀个元素开始,切到end_index - 1的元素为⽌
print(str1[-1:-6:-1])
# 结果是dlrow
print(str1[1:6:-1])
# 结果为空
# 切⽚时,⼀定要保证start_index到end_index的⽅向与步长step的⽅向同向,否则会切出空的序列
字符串拼接
Python的字符串格式化有三种⽅式: 百分号⽅式、format⽅式、f-strings⽅式
百分号⽅式
格式:%[(name)][flags][width].[precision]typecode
(name) 可选,⽤于选择指定的key
flags 可选,可供选择的值有:
+ 右对齐;正数前加正好,负数前加负号;
- 左对齐;正数前⽆符号,负数前加负号;
空格右对齐;正数前加空格,负数前加负号;
0 右对齐;正数前⽆符号,负数前加负号;⽤0填充空⽩处
width 可选,占有宽度
precision 可选,⼩数点后保留的位数
typecode 必选
s,获取传⼊对象的__str__⽅法的返回值,并将其格式化到指定位置
r,获取传⼊对象的__repr__⽅法的返回值,并将其格式化到指定位置
c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只⽀持0-255);字符:将字符添加到指定位置
o,将整数转换成⼋进制表⽰,并将其格式化到指定位置
x,将整数转换成⼗六进制表⽰,并将其格式化到指定位置
d,将整数、浮点数转换成⼗进制表⽰,并将其格式化到指定位置
e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(⼩写e)
E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(⼤写E)
f,将整数、浮点数转换成浮点数表⽰,并将其格式化到指定位置(默认保留⼩数点后6位)
F,同上
g,⾃动调整将整数、浮点数转换成浮点型或科学计数法表⽰(超过6位数⽤科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)G,⾃动调整将整数、浮点数转换成浮点型或科学计数法表⽰(超过6位数⽤科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)%,当字符串中存在格式化标志时,需要⽤ %%表⽰⼀个百分号
注:Python中百分号格式化是不存在⾃动将整数转换成⼆进制表⽰的⽅式
案例:
tpl = "i am %s" % "alex"
tpl = "i am %s age %d" % ("alex", 18)
tpl = "i am %(name)s age %(age)d" % {"name": "alex", "age": 18}
tpl = "percent %.2f" % 99.97623
tpl = "i am %(pp).2f" % {"pp": 123.425556, }
tpl = "i am %.2f %%" % 123.425556
format⽅式
格式:[[fill]align][sign][#][0][width][,][.precision][type]
fill 【可选】空⽩处填充的字符
align 【可选】对齐⽅式(需配合width使⽤)
<,内容左对齐
>,内容右对齐(默认)
=,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。即使:符号+填充物+数字
^,内容居中
hex字符串是什么sign 【可选】有⽆符号数字
+,正号加正,负号加负;
-,正号不变,负号加负;
空格,正号空格,负号加负;
# 【可选】对于⼆进制、⼋进制、⼗六进制,如果加上#,会显⽰ 0b/0o/0x,否则不显⽰
,【可选】为数字添加分隔符,如:1,000,000
width 【可选】格式化位所占宽度
.
precision 【可选】⼩数位保留精度
type 【可选】格式化类型
传⼊” 字符串类型 “的参数
s,格式化字符串类型数据
空⽩,未指定类型,则默认是None,同s
传⼊“ 整数类型 ”的参数
b,将10进制整数⾃动转换成2进制表⽰然后格式化
c,将10进制整数⾃动转换为其对应的unicode字符
d,⼗进制整数
o,将10进制整数⾃动转换成8进制表⽰然后格式化;
x,将10进制整数⾃动转换成16进制表⽰然后格式化(⼩写x)
X,将10进制整数⾃动转换成16进制表⽰然后格式化(⼤写X)
传⼊“ 浮点型或⼩数类型 ”的参数
e,转换为科学计数法(⼩写e)表⽰,然后格式化;
E,转换为科学计数法(⼤写E)表⽰,然后格式化;
f ,转换为浮点型(默认⼩数点后保留6位)表⽰,然后格式化;
F,转换为浮点型(默认⼩数点后保留6位)表⽰,然后格式化;
g,⾃动在e和f中切换
G,⾃动在E和F中切换
%,显⽰百分⽐(默认显⽰⼩数点后6位)
案例:
tpl = "i am {}, age {}, {}".format("seven", 18, 'alex')
tpl = "i am {}, age {}, {}".format(*["seven", 18, 'alex'])
tpl = "i am {0}, age {1}, really {0}".format("seven", 18)
tpl = "i am {0}, age {1}, really {0}".format(*["seven", 18])
tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18)
tpl = "i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18})
tpl = "i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33])
tpl = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1)
tpl = "i am {:s}, age {:d}".format(*["seven", 18])
tpl = "i am {name:s}, age {age:d}".format(name="seven", age=18)
tpl = "i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18})
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15)
tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)
f-strings⽅式
f-strings 提供⼀种简洁易读的⽅式, 可以在字符串中包含 Python 表达式. f-strings 以字母 'f' 或 'F' 为前缀, 格式化字符串使⽤⼀对单引号、双引号、三单引号、三双引号. 格式化字符串中。#!/usr/bin/env python
# -*-coding:utf-8-*-
"""
@author:fyh
@time:2019/6/5
"""
name = '豪仔'
age = 26
format_string1 = f'我的名字是 {name}, 我的年龄是 {age}'
print(format_string1) # 我的名字是豪仔, 我的年龄是 26
format_string2 = f"我的名字是 {name}, 我的年龄是 {age}"
print(format_string2) # 我的名字是豪仔, 我的年龄是 26
format_string3 = F'''我的名字是 {name}, 我的年龄是 {age}'''
print(format_string3) # 我的名字是豪仔, 我的年龄是 26
format_string4 = F"""我的名字是 {name}, 我的年龄是 {age}"""
print(format_string4) # 我的名字是豪仔, 我的年龄是 26
# 花括号中的数字会先运算
format_string5 = f'3 + 5 = {3 + 5}'
print(format_string5) # 3 + 5 = 8
a = 10
b = 20
format_string6 = f'3 + 5 = {a + b}'
print(format_string6) # 3 + 5 = 30
# 两个花括号会被替换为⼀个花括号, 注意{{}} 不表⽰表达式
format_string7 = F'我的名字是 {{name}}, 我的年龄是 {{age}}'
print(format_string7)
字节型(bytes)
Python3最重要的新特性之⼀是对字符串和⼆进制数据流做了明确的区分。⽂本总是Unicode,由str类型
表⽰,⼆进制数据则由bytes类型表⽰。Python3不会以任意隐式的⽅式混⽤str和bytes,你不能拼接字符串和字节流,也⽆法在字节流⾥搜索字符串(反之亦然),也不能将字符串传⼊参数为字节流的函数(反之亦然)。
回顾编码的发展史
在计算机历史的早期,美国为代表的英语系国家主导了整个计算机⾏业,26个英⽂字母组成了多样的英语单词、语句、⽂章。因此,最早的字符编码规范是ASCII码,⼀种8位即1个字节的编码规范,它可以涵盖整个英语系的编码需要。
编码是什么?编码就是把⼀个字符⽤⼀个⼆进制来表⽰。我们都知道,所有的东西,不管是英⽂、中⽂还是符号等等,最终存储在磁盘上都是01010101这类东西。在计算机内部,读取和存储数据归根结底,处理的都是0和1组成的⽐特流。问题来了,⼈类看不懂这些⽐特流,如何让这些010101对⼈类变得可读呢?于是出现了字符编码,它是个翻译机,在计算机内部某个地⽅,透明的帮我们将⽐特流翻译成⼈类可以直接理解的⽂字。对于⼀般⽤户,不需要知道这个过程是什么原理,是怎么执⾏的。但是对于程序员却是个必须搞清楚的问题。
以ASCII编码为例,它规定1个字节8个⽐特位代表1个字符的编码,也就是“00000000”这么宽,⼀个⼀个字节的解读。例如:01000001表⽰⼤写字母A,有时我们会“偷懒"的⽤65这个⼗进制来表⽰A在ASCII中
的编码。8个⽐特位,可以没有重复的最多表⽰2的8次⽅(255)个字符。
后来,计算机得到普及,中⽂、⽇⽂、韩⽂等等国家的⽂字需要在计算机内表⽰,ASCII的255位远远不够,于是标准组织制定出了叫做UNICODE的万国码,它规定任何⼀个字符(不管哪国的)⾄少以2个字节表⽰,可以更多。其中,英⽂字母就是⽤2个字节,⽽汉字是3个字节。这个编码虽然很好,满⾜了所有⼈的要求,但是它不兼容ASCII,同时还占⽤较多的空间和内存。因为,在计算机世界更多的字符是英⽂字母,明明可以1个字节就能够表⽰,⾮要⽤2个。
于是UTF-8编码应运⽽⽣,它规定英⽂字母系列⽤1个字节表⽰,汉字⽤3个字节表⽰等等。因此,它兼容ASCII,可以解码早期的⽂档。UTF-8很快就得到了⼴泛的应⽤。
在编码的发展历程中,我国还创造了⾃⼰的编码⽅式,例如GBK,GB2312,BIG5。他们只局限于在国内使⽤,不被国外认可。在GBK编码中,中⽂汉字占2个字节。
bytes和str的异同
回到bytes和str的⾝上。bytes是⼀种⽐特流,它的存在形式是010********这种。我们⽆论是在写代码,还是阅读⽂章的过程中,肯定不会有⼈直接阅读这种⽐特流,它必须有⼀个编码⽅式,使得它变成有意义的⽐特流,⽽不是⼀堆晦涩难懂的01组合。因为编码⽅式的不同,对这个⽐特流的解读也会不同,对实际使⽤造成了很⼤的困扰。下⾯让我们看看Python是如何处理这⼀系列编码问题的:
>>> s = "中⽂"
>>> s
'中⽂'
>>> type(s)
<class 'str'>
>>> b = bytes(s, encoding='utf-8')
>>> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>> type(b)
<class 'bytes'>
从例⼦可以看出,s是个字符串类型。Python有个内置函数bytes()可以将字符串str类型转换成bytes类型,
b实际上是⼀串01的组合,但为了在ide环境中让我们相对直观的观察,它被表现成了b'\xe4\xb8\xad\xe6\x96\x87'这种形式,开头的b表⽰这是⼀个bytes类型。\xe4是⼗六进制的表⽰⽅式,它占⽤1个字节的长度,因此”中⽂“被编码成utf-8后,我们可以数得出⼀共⽤了6个字节,每个汉字占⽤3个,这印证了上⾯的论述。在使⽤内置函数bytes()的时候,必须明确encoding的参数,不可省略。
我们都知道,字符串类str⾥有⼀个encode()⽅法,它是从字符串向⽐特流的编码过程。⽽bytes类型恰好有个decode()⽅法,它是从⽐特流向字符串解码的过程。除此之外,我们查看Python 源码会发现bytes和str拥有⼏乎⼀模⼀样的⽅法列表,最⼤的区别就是encode和decode。
从实质上来说,字符串在磁盘上的保存形式也是01的组合,也需要编码解码。
如果,上⾯的阐述还不能让你搞清楚两者的区别,那么记住下⾯两⼏句话:
1. 在将字符串存⼊磁盘和从磁盘读取字符串的过程中,Python⾃动地帮你完成了编码和解码的⼯作,你不需要关⼼它的过程。
2. 使⽤bytes类型,实质上是告诉Python,不需要它帮你⾃动地完成编码和解码的⼯作,⽽是⽤户⾃⼰⼿动进⾏,并指定编码格式。
3. Python已经严格区分了bytes和str两种数据类型,你不能在需要bytes类型参数的时候使⽤str参数,反
之亦然。这点在读写磁盘⽂件时容易碰到。
在bytes和str的互相转换过程中,实际就是编码解码的过程,必须显式地指定编码格式。
#!/usr/bin/env python3
# -*-coding:utf-8-*-
"""
@author:fyh
@time:2019/5/31
"""
# gbk编码的bytes
b = bytes('中国', encoding='gbk')
print(b) # b'\xd6\xd0\xb9\xfa'
print(type(b)) # <class 'bytes'>
str1 = str(b)
print(str1) # b'\xd6\xd0\xb9\xfa'
print(type(str1)) # <class 'str'>
# 指定编码格式
str2 = str(b, encoding='gbk')
print(str2) # 中国
print(type(str2)) # <class 'str'>
# 再把字符串str2转换为utf8编码格式的bytes类型:
b2 = bytes(str2, encoding='utf8')
print(b2) # b'\xe4\xb8\xad\xe5\x9b\xbd'
print(type(b2)) # <class 'bytes'>
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论