Python学习笔记21:文本与字节序列

Python学习笔记21:文本与字节序列

字符与字节

字符与字节是个编程里绕不开的话题,这东西属于那种一般平时用不到,但又不能不讲,而且还不容易理解的内容。

不过用类似的问题也很容易区分科班和非科班程序员。

话扯远了,我们回到字符和字节。从宏观上来说,字节就是机器编码,是方便于计算机存储的,而字符恰恰相反,是便于人类读写的。

最早的编码是什么我不清楚,不过ASCII应该是早期实用最广泛的编码。我现在依然能依稀回想起大学《C++大学教程》里那页ASCII编码表。

我们都知道,一个字节(byte)对应计算机里8个bit位,能表示2^8=256种可能性,对应的整数范围是0~255。

而ASCII就是用0~255编码了256种字符。

当然,这么“精简”的字符集在现代人看来会显得很不可思议,要知道现在可是个连emoji笑脸都要各种肤色都有的时代(大雾)。

所以我们发明了各种各样的编码来适应越来越多的需求,而UTF无疑是目前的佼佼者。

下面我们讨论一下Python中编码相关的各种问题。

转换

Python中字符和字节的转换很方便:

hellowStr = "Hellow world!"
hellowByte = bytes(hellowStr, encoding='ascii')
print(hellowByte)
print(hellowByte[0])
# 输出
# b'Hellow world!'
# 72

我们可以看到,字符串转换成了一个b'Hellow world'形式的东西,这个写法正是字节序列的字面量,也就是说我们可以用这种写法直接构建字节序列。

字节序列同样可以进行切片操作,可以看到第一个元素输出是72

可以通过百度百科查看ASCII编码表:

image-20210415162849981

可以看到72对应的正是大写字母H。

虽然我们可以实用str()bytes()进行转换,但更常用的字节编码/解码方式是实用encodingdecoding,我们看下面的例子:

hellowBytes = "Hellow wolrd!".encode(encoding='ascii')
print(hellowBytes)
print(hellowBytes[0])
hellowStr = hellowBytes.decode(encoding='ascii')
print(hellowStr)
# b'Hellow wolrd!'
# 72
# Hellow wolrd!

这种方式显式地表明了我们正在进行ASCII编码/解码工作。

老实说,我以前也经常对编码和解码傻傻分不清,很多时候只是手熟罢了。

要是细究的话,编码就是将字符串转化为目标编码,比如ASCII就是将字符对应到0~255这256个编码上。

这个概念不仅仅存在于字节编码,比如JSON,我们将程序中的原生容器序列化为JSON格式的文本,就是进行JSON编码,从JSON文本反序列化为原生容器就是在进行JSON解码。

对于字节编码,还有一种更便于理解的方式:编码就是将人类语言转换为机器码,解码就是将机器码转换成人类能理解的字符串。

字节数组

除了字节序列,Python还提供了字节数组作为字节操作的一种容器。

hellowBytes = "你好 世界!".encode(encoding='UTF-8')
print(hellowBytes)
print(hellowBytes[0:6])
subBytes = hellowBytes[0:6]
print(subBytes.decode(encoding='UTF-8'))
hellowByteArray = bytearray(hellowBytes)
print(hellowByteArray)
print(hellowByteArray[0:6])
print(hellowByteArray[0:6].decode(encoding='UTF-8'))
# b'\xe4\xbd\xa0\xe5\xa5\xbd \xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'
# b'\xe4\xbd\xa0\xe5\xa5\xbd'
# 你好
# bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd \xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81')
# bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd')
# 你好

这里我们实用了中文和UTF-8编码,可以更好的观察字节码和字符的区别。

可以看到,经过UTF-8编码,字节序列编程了类似\x??这种形式,而一个\x??正是两位16进制数。

UTF-8是一种变长编码,这说明其编码后的字节长度不确定。具体实现中会把一个字符编码为1~4个字节,其中1个字节是8位,正好可以表示为2位16进制数(2组2^4),也就是说示例中的\xe4正好表示一个字节。事实上大多数语言编码使用3字节就够了,很少有语言会用到4字节。

我们观察可以观察到一个明显的空格,这是因为UTF-8是兼容ASCII的,而控制台可以正常地显示ASCII编码符号。空格前正好是6字节,对应你好

UTF-8的百科词条见这里

此外,示例程序还展示了字节数组,其使用方式和字节序列极为相似。

内存视图

Python提供一个特殊容器memoryview,我们可以称它为内存视图。

内存视图可以提供一种在不创建副本的情况下操作数据的能力,其实质是一种内存共享技术。

with open(file='test.png',mode='rb') as fopen:
    imgView = memoryview(fopen.read(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值