对Python中bytes的学习心得
前言
本人使用Python已有5年时间,但由于从事的是深度学习行业,因此并没有对Python有过较深的研究和掌握。前些时间打算温故知新,重新阅读Python编程教程,无意中看到了Python中有bytes类型和相关方法,因此做了一些充电,在此记录一下自己的心得。
1、什么是bytes
Python中的bytes类型用来表示字符的字节编码,即将原始字符转换为不同类型的编码序列,转换后的编码以字节为单位存储。在C++等语言中字符和字符串是两种不同的类型,字符类型保存了单个字符,例如一个字母、数字、标点或特殊符号,它们一般占用内存的一个字节,也可以保存单个中文汉字或中文标点,一般占用两个字节容量。 ascii字符类型在C++等语言中可以直接参与算术运算,运算时每一个字符按它们各自的ascii码值作为数字表示。依然记得当时记了一些字符的ascii码,例如‘a’是97,‘A’是65等。 而在Python中没有字符这种类型,单个字符也会被当作字符串处理,因此为方便编码转换而有了bytes类型。bytes可以方便地将不同格式的文件读入而不至于产生乱码,如文本、图片、视频等,也能够方便数据在电脑之间或网上传输而避免乱码和缺失等问题。
2、bytes的用法—编码和解码
Python中提供了三种方式来将字符串转换为bytes类型: 1、对于字母、数字、英文标点这样的ascii字符,直接在其前面缀上‘b’即可,如下所示:
s = b'I am learning Python programming.'
print(s)
#结果输出:b'I am learning Python programming.'
输出结果表明,字符串s已经被转换为bytes类型了。 2、对于含有汉字等其它字符的字符串,可以使用bytes构造方法来实现转换,代码如下:
s = bytes('我正在学习Python编程', encoding='utf-8')
print(s)
#结果输出:b'\xe6\x88\x91\xe6\xad\xa3\xe5\x9c\xa8\xe5\xad\xa6\xe4\xb9\xa0Python\xe7\xbc\x96\xe7\xa8\x8b'
结果表明字符串也实现了bytes转换。方法中的‘encoding’参数用来指定编码类型,如‘utf-8’、’gbk‘、’gb2312‘等可以选择,不指定类型则默认为’utf-8’。对非ascii字符而言,不同的编码类型所得到的bytes值也不同,同时bytes编码也占用两个字节。 3、对于2中非ascii字符的情况,也可以使用encode方法实现bytes转换,代码如下:
s = '我正在学习Python编程'
print(s.encode('utf-8'))
#结果输出:b'\xe6\x88\x91\xe6\xad\xa3\xe5\x9c\xa8\xe5\xad\xa6\xe4\xb9\xa0Python\xe7\xbc\x96\xe7\xa8\x8b'
同时,Python也提供了将bytes类型字符串还原为原始字符串的decode方法,其参数为编码类型,使用方法如下:
s = b'Python'
print(s.decode('utf-8'))
#结果输出:Python
默认解码类型也是‘utf-8’,要注意的是解码类型要与s编码时的bytes类型一致,否则会出现转换错误,例如下列情况:
s = '我正在学习Python编程'.encode('utf-8')
print(s.decode('gbk'))
#结果输出:Traceback (most recent call last):
File "/Users/penny/PycharmProjects/Programming/test.py", line 10, in <module>
print(s.decode('gbk'))
UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 4: illegal multibyte sequence
解释器抛出UnicodeDecodeError异常,原因是字符串编码和解码所采用的规范不一致,导致了在解析非ascii字符时出现错误。 值得一提的是,在ascii字符集合中,不同编码规范下的bytes值是相同的,因此如果字符串中只包含这些字符,那么就算编码和解码不一致程序也不报错,如下测试所示:
s = 'Python'.encode('utf-8')
print(s.decode('gbk'))
#输出结果:Python
3、bytes的用法—字符的数值转换
既然bytes能够将字符串转换为编码序列,那么我们可以像C++那样将字符转换为数值类型,以满足编程中的需要。前面已经介绍过,C++中单个字符类型可以直接表示成对应的ascii数值,以便参与运算,而Python中是没有字符类型的,因此若要获取字符的编码值则需要借助下标索引。例如对字符串’ Python’,想要获取‘P’和’n’的编码值则需要使用以下方式:
s = b'Python'
print(s[0], s[5])
#输出结果:80 110
其中0和5对应着字符串中’P’和’n’的索引。对于汉字等非ascii字符,也需要先转换为bytes,再通过索引的方式获取编码值,只是汉字的编码值在一般程序设计中并不常用,值得注意的是由于汉字等字符的bytes为2个字节,因此编码中也由两个数值构成。
4、bytes的用法—文件的二进制读写
文件的读写操作分为普通和二进制两种,大多数情况下普通读写即可满足日常需求。二进制读写一般用于读取非文本文件时,例如图片、视频等。 我们探讨以二进制方式打开文本文件的情况,假设一个文本文件中保存了字符串’我正在学习Python编程’,以二进制将其打开并读入后,得到的就是该字符串的bytes类型,如下所示:
with open('a.txt', 'rb') as f:
print(f.read())
#文件‘a.txt’中的内容:我正在学习Python编程
#输出结果:b'\xe6\x88\x91\xe6\xad\xa3\xe5\x9c\xa8\xe5\xad\xa6\xe4\xb9\xa0Python\xe7\xbc\x96\xe7\xa8\x8b'
而以二进制写入文本文件时,需要以bytes类型的字符串作为输入,否则程序就会报错,如下所示:
with open('a.txt', 'wb') as f:
print(f.write('我正在学习Python编程'))
#输出结果:Traceback (most recent call last):
File "/Users/penny/PycharmProjects/Programming/test.py", line 6, in <module>
print(f.write('我正在学习Python编程'))
TypeError: a bytes-like object is required, not 'str'
错误提示为TypeError,要求输入必须为bytes相关类型。 我们将上文中的‘我正在学习Python编程’对应的bytes类型作为write函数的输入,以观察a.txt中的内容变化,结果如下所示:
with open('a.txt', 'wb') as f:
print(f.write(b'\xe6\x88\x91\xe6\xad\xa3\xe5\x9c\xa8\xe5\xad\xa6\xe4\xb9\xa0Python\xe7\xbc\x96\xe7\xa8\x8b'))
#程序执行前,a.txt内容为空。程序执行后,内容变为‘我正在学习Python编程’
由上述文件IO的测试结果表明,Python中的bytes类型也是用于二进制文件的输入和输出的。这里要注意的一点是bytes的编码必须和文件打开时指定的编码一致,否则也会报错。 好了,对于bytes的学习心得就分享到这了,如果小伙伴们阅读时发现了错误或不足之处,可以随时向博主提出哦,博主先闪了!
|