资讯专栏INFORMATION COLUMN

PyTips 0x08 - Python 字节与字节数组

Leo_chen / 1691人阅读

摘要:回到对字节和字节数组的定义为了用计算机可以理解的数字描述人类使用的字符,我们需要一张数字与字符对应的表。由于和字符串一样是序列类型,字节和字节数组可用的方法也类似,这里就不一一列举了。

项目地址:https://git.io/pytips

0x07 中介绍了 Python 中的字符串类型,字符串类型是对人类友好的符号,但计算机只认识一种符号,那就是二进制(binary)数,或者说是数字:

上面这张图片来自 OpenCV,非常直观地解释了计算机处理的信息与我们看到的图像之间的关系。回到 Python 对字节和字节数组的定义:

The core built-in types for manipulating binary data are bytes and bytearray.

1Byte of ASCII

为了用计算机可以理解的数字描述人类使用的字符,我们需要一张数字与字符对应的表。我们都知道在计算机中 1 byte = 8bits,可以存储 0~255 共256个值,也就是说 1byte 最多可以表示 256 个字符,在最初的计算机世界中,256 足以容纳所有大小写英文字母和 0~9 阿拉伯数字以及一些常用的符号,于是就有了 ASCII 编码:

在 Python 中创建字节与字符串类似,只不过需要在引号外面加一个前缀b

print(b"Python")
python = (b"P" b"y" b"t" b"o" b"n")
print(python)
b"Python"
b"Pyton"

Bytes 代表的是(二进制)数字的序列,只不过在是通过 ASCII 编码之后才是我们看到的字符形式,如果我们多带带取出一个字节,它仍然是一个数字:

print(b"Python"[0])
80

我们可以用 b"*" 的形式创建一个字节类型,前提条件是这里的 * 必须是 ASCII 中可用的字符,否则将会超出限制:

print(b"雨")
  File "", line 1
    print(b"雨")
         ^
SyntaxError: bytes can only contain ASCII literal characters.

错误提示说明:字节类型只能允许 ASCII 字符。

0~127~255

那么问题来了,我们发现上面的 ASCII 表里面所有的字符只占据了 [31, 127],那对于这一范围之外的数字我们要怎么才能表示为字节类型?答案就是用特殊的转义符号x+十六进制数字 :

print(b"xff"[0])
print(b"x24")
255
b"$"

反过来我们也可以将数字(0~255)转变成转义后的字节类型:

print(bytes([24]))
print(bytes([36,36,36])) # 记住字节类型是一个序列
b"x18"
b"$$$"

或者直接从十六进制得来:

print(bytes.fromhex("7b 7d"))

# 逆运算
print(b"{ }".hex())

int(b" ".hex(), base=16)
b"{}"
7b207d
32
encode

字符串有 decode 方法,而字节有 encode 方法,我们这里先简单看一下 encode("ascii") 。对于给定的字符我们可以通过编码得到它在编码表里面的坐标(即码位),因此对字符进行encode("ascii")操作是找到其在 ASCII 中的位置:

print("$".encode("ascii"))
print("$".encode("ascii")[0])
b"$"
36

也就是说字符 "$" (0x07中已经介绍过这是一个 Unicode 编码的字符)在 ASCII 中的位置就是 $(或者说36)。

可是如果我们对一些奇怪的字符进行 ASCII 编码,就会发生:

snake = "?"
try:
    snake.encode("ascii")
except UnicodeEncodeError as err:
    print(err)

# 正确的做法应该是用 UTF-8 进行编码,因为字符串都是 UTF-8 的
print(snake.encode()) # utf-8 by default
"ascii" codec can"t encode character "U0001f40d" in position 0: ordinal not in range(128)
b"xf0x9fx90x8d"

于是就得到了我们最熟悉的错误:ordinal not in range(128),至于为什么是 128,现在应该很好理解了吧!

字节数组

和字符串一样,字节类型也是不可变序列,而字节数组就是可变版本的字节,它们的关系就相当于listtuple

ba = bytearray(b"hello")
ba[0:1] = b"w"
print(ba)
bytearray(b"wello")

由于和字符串一样是序列类型,字节和字节数组可用的方法也类似,这里就不一一列举了。

总结

字节(字节数组)是二进制数据组成的序列,其中每个元素由8bit二进制即1byte亦即2位十六进制数亦亦即0~255组成;

字节是计算机的语言,字符串是人类语言,它们之间通过编码表形成一一对应的关系;

最小的 ASCII 编码表只需要一位字节,且只占用了其中 [31,127] 的码位;

关于字节与字符串之间的关系,将在下一期[0x08]()详细介绍。

参考

Pragmatic Unicode


欢迎关注公众号 PyHub!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37834.html

相关文章

  • PyTips 0x09 - Python 中 Unicode 的正确用法

    摘要:只包含了个基本拉丁字母阿拉伯数目字和英式标点符号一共个字符,因此只需要不占满一个字节就可以存储,而则涵盖的数据除了视觉上的字形编码方法标准的字符编码外,还包含了字符特性,如大小写字母,共可包含个字符,而到现在只填充了其中的个位置。 项目地址:https://git.io/pytips 0x07 和 0x08 分别介绍了 Python 中的字符串类型(str)和字节类型(byte),以及...

    shenhualong 评论0 收藏0
  • PyTips 0x07 - Python 字符串

    摘要:项目地址所有用过的人应该都看过下面两行错误信息这就是界的锟斤拷今天和接下来几期的内容将主要关注中的字符串字节及两者之间的相互转换。 项目地址:https://git.io/pytips 所有用过 Python (2&3)的人应该都看过下面两行错误信息: UnicodeEncodeError: ascii codec cant encode characters in position...

    go4it 评论0 收藏0
  • WebSocket协议以及ws源码分析

    摘要:本文包括如下内容协议第四章连接握手协议第五章数据帧库源码分析连接握手过程库源码分析数据帧解析过程参考协议深入探究本文对的概念定义解释和用途等基础知识不会涉及稍微偏干一点篇幅较长大约行阅读需要耐心连接握手过程关于有一句很常见的话复用 ¿ 本文包括如下内容: WebSocket协议第四章 - 连接握手 WebSocket协议第五章 - 数据帧 nodejs ws库源码分析 - 连接...

    ytwman 评论0 收藏0
  • PyTips 0x05 - Python 函数参数解包

    摘要:这里的关键词函数必须明确指明,不能通过位置推断则代表任意数量的关键词参数添加的新特性,使得可以在函数参数之外使用这里的逗号不能漏掉所谓的解包实际上可以看做是去掉的元组或者是去掉的字典。 项目地址:https://git.io/pytips 函数调用的参数规则与解包 Python 的函数在声明参数时大概有下面 4 种形式: 不带默认值的:def func(a): pass 带有默认值的...

    pubdreamcc 评论0 收藏0
  • PyTips 0x10 - Python 的堆优先队列

    摘要:项目地址中内置的库和分别提供了堆和优先队列结构,其中优先队列本身也是基于实现的,因此我们这次重点看一下。堆可以用于实现调度器例见之协程,更常用的是优先队列例如。 项目地址:https://git.io/pytips Python 中内置的 heapq 库和 queue 分别提供了堆和优先队列结构,其中优先队列 queue.PriorityQueue 本身也是基于 heapq 实现的,因...

    dreambei 评论0 收藏0

发表评论

0条评论

Leo_chen

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<