流畅的python——4月28日读书笔记

第四章 文本和字节序列

今天终于开启第四章啦,这部分也是我平常生活中用的比较多,但是也查的最多的一部分,总是把一些东西搞混,这次系统的学一学,争取拿下!!

我们人类在编程中都是使用文本字符串,不会说用二进制序列、字节序列去编代码。但是我们的计算机却使用的是字节序列,那么中间就需要一个翻译将unicode字符串和二进制序列做转换。

4.1 4.1 4.1 字符问题
字符串,简单来讲,一个字符串就是一个字符序列。
unicode标准将字符的标识和具体的字节表述进行了一下区分:

  • 字符的标识——即码位。是0~1114111的数字(十进制),在unicode标准中以4~6个十六进制的数字表示,而且要加前缀U+。
  • 字符的具体表示取决于所用的编码。编码是在码位和字节序列之间转换时用到的算法。

举个?:
字母A的码位是U+0041,在UTF-8编码中,A的码位编码为单个字节\x41,而在UTF-16中,编码成了两个字节\x41\x00。

将码位变成字节序列的过程称为编码,把字节序列转换为码位的过程是解码。
示例如下:

>>> s = 'iam刘'
>>> len(s)
4
>>> b = s.encode('utf8')
>>> b
b'iam\xe5\x88\x98'
>>> len(b)
6
>>> b.decode()
'iam刘'

可以得知,汉字被utf-8编码成了3个字节。
解码之后,该序列的长度由原先的4个字节变成了6个字节。
其中 bytes的字面量是以b开头的。

4.2 4.2 4.2 字节概要

python 中内置了两种基本的二进制序列类型:python3的bytes类型和python2.6中添加的bytearray。

bytes和bytearray对象的元素是介于0~255之间的整数。然而二进制的序列切片始终是同一类型的二进制序列,包括长度为1的切片。
示例如下:

>>> name = bytes('iam刘',encoding='utf_8')
>>> name
b'iam\xe5\x88\x98'
>>> name[0]
105
>>> name[:1]
b'i'
>>> name_arr = bytearray(name)
>>> name_arr
bytearray(b'iam\xe5\x88\x98')
>>> name_arr[-1:]
bytearray(b'\x98')

bytes对象的切片还是bytes的对象,bytearray对象的切片还是bytearray对象。我们可以用给定的编码去构建。

虽然二进制的序列其实是整数序列,但是它们的字面量表示法表明其中有ASCII文本。所以各个字节的值可能会使用下列三种不同的方式显示:

  • 可打印的ASCII范围内的字节(从空格到~),使用ASCII字节本身。
  • 制表符、换行符、回车符和\对应的字节,使用转义序列\t,\n,\r和\。
  • 其他字节的值,使用16进制转义字符。

因此,在“iam刘”的实例中,iam在ASCII的范围内可以被直接打印出来,而“刘”则被转义了。

str类型的很多方法都支持bytes和bytearray类型使用。这意味着,我们可以使用熟悉的字符串方法来处理二进制的序列,包括re模块的正则表达式也可以处理二进制序列。

构建bytes或bytearray的方式示例如下:

>>> b = bytearray(2)
>>> b
bytearray(b'\x00\x00')
>>> b = bytes(13)
>>> b
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

>>> b_list = bytes(array.array('i', [-1, -3, 0, 2, 4]))
>>> b_list
b'\xff\xff\xff\xff\xfd\xff\xff\xff\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00'

它可以是一个str对象和一个encoding关键字参数。
也可以是一个可迭代对象,提供0~255之间的数值。
一个整数,使用空字节创建对应长度的二进制序列。
一个实现了缓冲协议的对象;此时是将源对象中的字节序列复制到新建的二进制序列中去。

那么如果你想要从二进制的序列中提取一些结构化的信息,可以使用struct模块。

结构体和内存视图

struct模块提供了一些函数,将打包的字节序列可以转化成不同类型的字段所组成的元组。

>>> import struct
>>> v1 = 1
>>> bytes = struct.pack('i',v1)
>>> bytes
b'\x01\x00\x00\x00'

这里有一个完整的fmt列表:
在这里插入图片描述

pack的时候,会按照对应的fmt方式将原值转化为string。

4.3 4.3 4.3 基本的编解码器

python有超过100种的编解码器,用于在文本和字节之间的相互转化。我们常用的如’utf-8’,'utf-16’等都是编解码器的一种。

这些名称,是我们编解码时会用到的参数。
例如:

>>> str = '你好'
>>> str_2 = str.encode('utf-8')
>>> str_2
b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> str3 = str_2.decode('utf-16')
>>> str3
'뷤\ue5a0붥'

你好直接被解码成火星韩语了?

4.4 4.4 4.4 了解编解码问题

处理UnicodeEncodeError——把文本转换成字节序列时,如果目标编码中并不存在某个字符,则会抛出UnicodeEncodeError异常。

示例如下:

>>> city = '?️'
>>> city.encode('utf_8')
b'\xf0\x9f\x89\x90\xef\xb8\x8f'
>>> city.encode('cp437')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#  File "/usr/local/var/pyenv/versions/3.6.6/lib/python3.6/encodings/cp437.py", line 12, in encode
#    return codecs.charmap_encode(input,errors,encoding_map)
#  UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-1: character maps to <undefined>

同样的,并不是每一个字符序列都是有效的utf-8或utf-16。所以,我们将二进制序列变成文本时,假设是这两个编码中的一个,那么当遇到无法转换的字节序列时,就会抛出UnicodeDecodeError。

示例如下:

>>> my_byte = b'Montr\xe9al'
>>> my_byte.decode('utf_8')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#  UnicodeDecodeError: 'utf-8' codec can't #  decode byte 0xe9 in position 5: invalid #  continuation byte
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值