# str、bytes和bytearray

# str 和 bytes

总体来说,Python中的bytes​和str​类型都是用来表示序列的数据类型,不同的是bytes​类型表示的是字节序列,每个元素都是一个字节,而str​类型表示的是字符序列,每个元素是一个Unicode字符,而这些码位的具体存储方式则有不同的实现,有utf-8​、utf-16​等多种,这些具体存储方式下的二级制形式实际上就是字符串对应的字节序列。

bytes​是一种不可变的二进制数据类型,用于表示字节串(byte string)。bytes​对象的每个元素都是一个字节,取值范围为0-255。

bytes​类型是不可变的,可以通过字面量或者bytes()​构造函数创建,支持一些基本的操作,例如索引、切片、拼接等但由于其不可变性,每个操作都会返回一个新的bytes​对象。同时,bytes​对象还提供了一些实用的方法,例如decode()​方法用于将字节串解码为字符串,hex()​方法用于返回一个十六进制表示的字符串等。

需要注意的是,bytes​对象和str​对象之间的转换需要进行编码和解码操作,例如bytes​对象可以通过调用decode()​方法来解码为字符串,而字符串则可以通过调用encode()​方法来编码为bytes​对象。在进行编码和解码时,需要指定正确的编码格式,例如UTF-8、GB2312等。

>>> s = "I am a str. 123"
>>> print(s)
I am a str. 123
>>> print(type(s))
<class 'str'>
>>> b = s.encode('utf-8')
>>> print(b)
b'I am a str. 123'
>>> print(type(b))
<class 'bytes'>
>>> s1 = b.decode('utf-8')
>>> s == s1
True
>>> s is s1
False
>>> for i in s:
...     print('-> ',i) 
... 
->  I
->   
->  a
->  m
->   
->  a
->   
->  s
->  t
->  r
->  .
->   
->  1
->  2
->  3
>>> 
>>> 
>>> for i in b:
...     print('-> ',i) 
... 
->  73
->  32
->  97
->  109
->  32
->  97
->  32
->  115
->  116
->  114
->  46
->  32
->  49
->  50
->  51
>>> 
>>> for i in b: 
...     print('-> ',chr(i))
... 
->  I
->
->  a
->  m
->
->  a
->
->  s
->  t
->  r
->  .
->
->  1
->  2
->  3

# bytearray

bytearray​ 是 Python 中一种可变的字节串类型,可以对其进行修改操作,其创建方式与 bytes​ 类型类似,可以使用字面量或构造函数。

str​ 类型相比,bytearray​ 和 bytes​ 类型都是面向字节的,可以用于处理二进制数据,而 str​ 则是面向 Unicode 字符的。bytes​ 和 bytearray​ 的区别在于,前者是不可变的,后者是可变的。

s = 'hello'  # str 类型
b = s.encode('utf-8')  # 转为 bytes 类型
ba = bytearray(b)  # 转为 bytearray 类型

# str与bytes的混用

在Python中,str和bytes是非常相像的,两种对象都支持在%​的右边作为元素去填充左边的格式化字符串,除了各自类型的同类型填充,bytes​可以填充str​的格式化字符串,str​却并不能填充bytes​的格式化字符串。实际上原因很简单,bytes​填充str​字符串时实际上是调用了bytes​的__repr__​方法,因此填入的是b'...'​,而不是真正其代表的字符串;对于使用str​去填充bytes​串的情况,是因为bytes​根本不知道以什么格式去将str​编码成bytes​。

经过尝试,可以看到,在Python3中已经移除了对bytes​对象的format​支持。

>>> s = "str.{}".format(b'bytes')  
>>> s
"str.b'bytes'"
>>> b = b"bytes.%s" % (b"str") 
>>> b
b'bytes.str'
>>> b = b"bytes.{}".format(b"str")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'bytes' object has no attribute 'format'
>>> b = b"bytes.%s"%("str")      
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'