Python 2.6和3中的bytes与bytearray

37 投票
5 回答
47820 浏览
提问于 2025-04-15 16:03

我正在尝试了解在Python 2.6中,bytesbytearray之间的区别,但有些地方我不太明白。

当我用bytes来遍历时,它会返回字符串:

for i in bytes(b"hi"):
    print(type(i))

结果是:

<type 'str'>
<type 'str'>

但是当我用bytearray来遍历时,它会返回int类型的数字:

for i in bytearray(b"hi"):
    print(type(i))

结果是:

<type 'int'>
<type 'int'>

为什么会有这样的区别呢?

我想写一些代码,能够顺利迁移到Python 3。那么在Python 3中情况也是这样吗?

5 个回答

8

简而言之

在python2.6及以上版本中,bytesstr 是一样的,等于python3.x中的bytes,但不等于python3.x中的str

python2.6及以上版本中的bytearray 和 python3.x中的bytearray 是一样的。

python2.x中的unicode 和 python3.x中的str 是一样的。

详细解答

在python 3.x中,bytesstr 的含义发生了变化。

简单回答你的问题,在python 2.6中,bytes(b"hi") 是一个不可变的字节数组(每个字节8位)。所以每个byte的类型就是byte,这和python 2.6及以上版本中的str是一样的(但在python 3.x中就不是这样了)。

bytearray(b"hi") 是一个可变的字节数组。当你查看它的类型时,它是int,因为python把bytearray中的每个元素表示为0到255之间的整数(这是8位整数的所有可能值)。而bytes数组中的元素则表示为该字节的ASCII值。

例如,在Python 2.6+中:

>>> barr=bytearray(b'hi')
>>> bs=bytes(b'hi')
>>> barr[0] # python shows you an int value for the 8 bits 0110 1000
104 
>>> bs[0] # python shows you an ASCII value for the 8 bits 0110 1000
'h'
>>> chr(barr[0]) # chr converts 104 to its corresponding ASCII value
'h'
>>> bs[0]==chr(barr[0]) # python compares ASCII value of 1st byte of bs and ASCII value of integer represented by first byte of barr
True

现在,python 3.x的情况完全不同。你可能会觉得奇怪,为什么在python2.6+中str字面量会表示为byte。好吧,这个回答解释了这个问题

在Python 3.x中,str 是Unicode文本(之前只是字节数组,注意Unicode和字节是完全不同的东西)。bytearray 是一个可变字节数组,而bytes 是一个不可变字节数组。它们几乎有相同的功能。现在如果我在python 3.x中再次运行上面的代码,结果如下。在Python 3.x中:

>>> barr=bytearray(b'hi')
>>> bs=bytes(b'hi')
>>> barr[0]
104
>>> bs[0]
104
>>> bs[0]==barr[0] # bytes and bytearray are same thing in python 3.x
True

在python 3.x中,bytesbytearray 是相同的,除了可变性。

你可能会问str发生了什么?在python 3中,str被转换成了python 2中的unicode,而unicode类型随后在python 3中被移除,因为它是多余的。

我想写一些代码,能够很好地转换到Python 3中。那么在Python 3中的情况是一样的吗?

这要看你想做什么。你是在处理字节,还是在处理字节的ASCII表示?

如果你在处理字节,那么我的建议是在Python 2中使用bytearray,它在python 3中是一样的。但如果这对你来说重要的话,你会失去不可变性。

如果你在处理ASCII或文本,那么在Python 2中将你的字符串表示为u'hi',在python 3中有相同的含义。'u'在Python 2中有特殊含义,指示python 2将字符串字面量视为unicode类型。在python 3中,'u'没有任何意义,因为在python 3中所有字符串字面量默认都是Unicode(这在python 3中被混淆地称为str类型,而在python 2中称为unicode类型)。

41

对于(至少)Python 3.7

根据文档:

bytes 对象是不可变的单字节序列。

bytearray 对象是可变的字节对象。

这就是 bytesbytearray 的主要区别。实际上,它们是相当可以互换的,设计得足够灵活,可以在操作中混合使用而不会出错。实际上,官方文档中有一整节专门展示 bytesbytearray 之间的相似之处。

文档中提供了一些线索,解释了原因:

由于许多主要的二进制协议是基于ASCII文本编码的,bytes 对象提供了几个仅在处理与ASCII兼容的数据时有效的方法,并且在多种其他方面与字符串对象密切相关。

32

在Python 2.6中,bytes只是str的一个别名
这个“伪类型”是为了让程序和程序员提前做好准备,以便将来能更好地适应Python 3.0。在Python 3.0中,str和bytes有严格的区别:str是用来处理文本的(它们是系统性地使用unicode),而bytes则是用来存储数据的(它们是字节数组,不适合用来处理文本)。

同样,在2.6版本中,字符串前面的b前缀并没有实际效果,但它在程序中是一个有用的标记,明确表示程序员希望这个字符串作为数据字符串,而不是文本字符串。这些信息可以在程序迁移到Python 3时,被2to3转换器或类似工具使用。

你可以查看这个SO问题以获取更多信息。

撰写回答