37

我正在Python 2.6 中尝试使用bytesvs。bytearray我不明白一些差异的原因。

bytes迭代器返回字符串:

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

给出:

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

但是bytearray迭代器返回ints:

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

给出:

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

为什么有区别?

我想编写可以很好地转换为 Python 3 的代码。那么,Python 3 中的情况是否相同?

4

5 回答 5

40

对于(至少)Python 3.7

根据文档:

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

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

bytes就vs而言,这几乎就是这样bytearray。事实上,它们是相当可互换的,并且设计得足够灵活,可以在操作中混合而不会引发错误。事实上,官方文档bytes中有一整节专门展示了 api和api的相似之处bytearray

文档中有关原因的一些线索:

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

于 2018-12-13T03:43:18.903 回答
30

在 Python 2.6 中,字节只是 str 的别名
这种“伪类型”被引入 [部分] 准备程序 [和程序员!] 以转换/兼容 Python 3.0,其中对 str (系统地是 unicode)和 bytes (这是数组)的语义和使用有严格的区别八位字节,用于存储数据,但不是文本)

类似地,字符串文字的 b 前缀在 2.6 中无效,但它在程序中是一个有用的标记,它明确地标记了程序员将字符串作为数据字符串而不是文本字符串的意图。当程序移植到 Py3k 时,2to3 转换器或类似实用程序可以使用此信息。

您可能需要查看此SO Question以获取更多信息。

于 2009-11-16T08:09:55.763 回答
8

TL;博士

python2.6+ bytes= python2.6+ str= python3.x bytes!= python3.xstr

python2.6+ bytearray= python3.xbytearray

python2.x unicode= python3.xstr

长答案

bytes并且str自 python 3.x 以来在 python 中的含义发生了变化。

首先要简短回答您的问题,在 python 2.6bytes(b"hi")中是一个不可变的字节数组(8 位或八位字节)。所以 each 的类型bytebyte中的相同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文字意味着 a是很奇怪的。byte那么这个答案解释了

在 Python 3.x 中,anstr是一个 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

bytes并且bytearray在 python 3.x 中是相同的,除了可变性。

你可能会问发生了什么事strstr在 python 3 中被转换为unicodepython 2 中的内容,并且unicodetype 随后从 python 3 中删除,因为它是多余的。

我想编写可以很好地转换为 Python 3 的代码。那么,Python 3 中的情况是否相同?

这取决于你想要做什么。您是在处理字节还是在处理字节的 ASCII 表示?

如果您正在处理 bytes,那么我的建议是bytearray在 Python 2 中使用,这在 python 3 中是相同的。但是如果这对您来说很重要,那么您会失去不变性。

如果您正在处理 ASCII 或 text,则将您的字符串表示为u'hi'在 Python 2 中,这在 python 3 中具有相同的含义。'u'在 Python 2 中具有特殊含义,它指示 python 2 将字符串文字视为unicode类型。python 3 中的 'u' 没有意义,因为默认情况下 Python 3 中的所有字符串文字都是 Unicode(str在 python 3 中被混淆地称为 type,unicode在 python 2 中称为 type)。

于 2019-01-31T14:46:50.933 回答
3

我不确定从哪个版本开始,但bytes实际上是一个str,如果你这样做,你可以看到type(bytes(b"hi"))-> <type 'str'>

bytearray是一个可变的字节数组,其中一个构造函数接受一个字符串。

于 2009-11-16T08:09:03.933 回答
3

我在 Python 3.0 上尝试过。

在 Python 3.0 中,bytes迭代器返回ints,而不是 Python 2.6 中的字符串:

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

给出:

<class 'int'>
<class 'int'>

bytearray迭代器也返回s class 'int'

于 2009-11-19T02:37:54.687 回答