摘自官方Python documentation:
由于字节对象是整数序列(类似于元组),对于字节对象b,b [0]将是整数,而b [0:1]将是长度为1的字节对象。
我很困惑为什么设计师选择这样做,因为byte
只是8位而int
通常是32位。
有人可以解释为什么b[0]
是int
背后的原因吗?谢谢!
编辑:我尝试了以下实验:
>>> import sys
>>> b = bytes(100)
>>> sys.getsizeof(b)
133
>>> sys.getsizeof(list(b))
1008
似乎bytes
由内存中的字节表示;但问题仍然是为什么迭代bytes
为int
?
bytes
对象不存储int
s。对bytes
对象进行索引或迭代会产生int
s,但bytes
对象会将字节存储为字节。对象开销仅对整个bytes
对象产生一次。
从bytes
对象中提取的单个字节用与任何其他整数相同的整数类型表示,因为没有其它方面的做法。由于CPython存储小整数的规范副本,因此将字节存储为普通int
的唯一成本是指针的成本。
为此创建一个专用的byte
类型仍然会在标准的64位CPython构建上为每个byte
对象花费16个字节的对象开销,加上1个字节用于数据,加上8个字节用于指针,净丢失为17个字节只存储int
的指针。当然,你可以存储规范的byte
对象,但这仍然没有给你现有的规范int
s带来任何好处。此外,byte
类型会增加需要与byte
交互的代码的额外复杂性。
在CPython的数据模型中以比每次使用整数更少的字节存储字节的唯一方法是使用压缩表示,并且包装表示就是bytes
本身。
一个字节可以表示为低于2 ** 8或低于256的int
。这是为了更容易重写字节对象的字节。
注意:当您创建一个bytes对象时,它会显示:
bytes(iterable_of_ints) -> bytes
这意味着一个字节对象只有很多整数但变成了编码字节。
将字节对象视为整数列表。看一下这个:
>>> l = [1, 36, 233]
>>> b = bytes(l)
>>> l[0]
1
>>> b[0]
1
>>> l[0:1]
[1]
>>> b[0:1]
b'\x01'
现在关于为什么这个问题?
还有什么方法可以表示一个字节? 字符串肯定会用编码表示许多字节,但如果它具有不同的编码或没有指定编码则不会。 一个元组没有意义,因为它里面可以有任何东西。这包括其他字符串,浮点数和一个字节不代表的其他东西。 一个整数只代表一个字节,专门为此目的的一个元组元组可以工作。
因此,int
s的元组将组成bytes
对象,并且bytes
对象将能够被解码并编码成字符串以供使用。 int
将是在bytes
对象中表示单个字节的唯一“纯粹”方式。