06-02字符串与bytes

字符串与bytes

python2和python3最大的区别

区别之处

  • str是文本序列

  • bytes是字节序列

  • 文本是有编码的(utf-8, gbk, GB18030等)

  • 字节没有编码的这种说法。

  • 文本的编码指的是字符如何使用字节表示。

bytes与str关系

  • python3字符串默认使用utf-8编码
  • str转bytes:s.encode()
    • 默认使用utf-8
    • s.encode(‘GBK‘)# 指定传递不同的编码
  • bytes转str:b.decode()
  • bytes转二进制:bin(0xe9),str不能直接转二进制
  • 跨网络交互,如果双方没有使用协定的编码处理,那么就会产生乱码。python3中统一发送bytes, 然后通过某种方式协商编码。
    • 在Python2中,要么遇不到,要么遇到了无法解决, 所以在Python3中很好的解决了这个问题。
  • string的所有操作bytes都支持
In [46]: s = ‘马哥教育‘

In [47]: type(s)
Out[47]: str

In [48]: s.encode()   # 把字符串编码为bytes
Out[48]: b‘\xe9\xa9\xac\xe5\x93\xa5\xe6\x95\x99\xe8\x82\xb2‘

In [49]: ‘马‘.encode()   # 将‘马‘抓换为bytes
Out[49]: b‘\xe9\xa9\xac‘

In [50]: ‘哥‘.encode()   # 将‘哥‘转换为bytes
Out[50]: b‘\xe5\x93\xa5‘

In [54]: 0xe9    # 16进制,encode一般是去掉0
Out[54]: 233

In [55]: 0xa9
Out[55]: 169

In [56]: 0xac
Out[56]: 172

In [57]: bin(0xe9)    # 转换为二进制
Out[57]: ‘0b11101001‘

In [58]: bin(0xa9)
Out[58]: ‘0b10101001‘    # 0b代表的是二进制

In [59]: bin(0xac)
Out[59]: ‘0b10101100‘

In [60]: 11101001 10101001 10101100   # 马字在计算机中的表示

In [61]: s.encode(‘GBK‘)   # 指定传递不同的编码
Out[61]: b‘\xc2\xed\xb8\xe7\xbd\xcc\xd3\xfd‘

In [62]: s.encode()    # 默认使用utf-8
Out[62]: b‘\xe9\xa9\xac\xe5\x93\xa5\xe6\x95\x99\xe8\x82\xb2‘

In [64]: b = s.encode()   # 将utf-8转换为bytes存储

In [65]: b
Out[65]: b‘\xe9\xa9\xac\xe5\x93\xa5\xe6\x95\x99\xe8\x82\xb2‘

In [66]: b.decode()   # 把bytes转换为str
Out[66]: ‘马哥教育‘

In [67]: type(b)
Out[67]: bytes

In [68]: b.decode(‘GBK‘)   # utf-8无法转换为GBK
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-68-041bea7b9d7a> in <module>()
----> 1 b.decode(‘GBK‘)

UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xac in position 2: illegal multibyte sequence

跨网络交互, 如果双方没有使用协定的编码处理,那么就会产生乱码。
python3中统一发送bytes, 然后通过某种方式协商编码。

在Python2中,要么遇不到,要么遇到了无法解决, 所以在Python3中很好的解决了这个问题。

string的所有操作bytes都支持

bytes的创建

  • bytes由str通过encode方法转换得到
  • 通过b前缀直接定义bytes
In [4]: b = b‘abc‘

In [5]: type(b)
Out[5]: bytes

In [6]: b.decode()
Out[6]: ‘abc‘

bytes操作

除了encode外, str操作, 都有对应bytes的版本, 但是传入参数必须是bytes。
bytes操作是按照字节来的

In [7]: b.‘abc‘.find(‘b‘)   # 参数必须也是bytes
  File "<ipython-input-7-f89f1c2c6bad>", line 1
    b.‘abc‘.find(‘b‘)
          ^
SyntaxError: invalid syntax

In [8]: b‘abc‘.find(b‘b‘)   # 参数必须是bytes
Out[8]: 1

In [10]: ‘马哥教育‘.encode().find(b‘\xa9‘)   # bytes操作是按照字节来的
Out[10]: 1

In [11]: len(‘马哥教育‘.encode())   # 按照字节来的
Out[11]: 12

In [13]: b.decode()   # 转换为str
Out[13]: ‘abc‘

In [14]: b.hex 
Out[14]: <function bytes.hex>

In [15]: b.hex()   # 转换为16进制
Out[15]: ‘616263‘

bytearray

  • bytearray是bytes的可变版本
  • str和bytes是不可变的
  • bytes为什么需要一个可变的版本?
    • 图片处理, 修改几个像素的时候, bytes无法原地修改, 如果一个图片3M修改1000次就需要3G的内存, bytearray为了针对这种场景的。大对象的二进制文件做一些原地处理。
  • str为什么没有一个可变版本?
    • 因为str没有那么大的对象,如果有, 可以先转换为bytearray, 然后再进行处理, 所以不需要。
  • 相对于bytes来说, 多了insert, append, extend, pop, remove, clear, reverse原地修改的方法。
  • 为什么bytearray插入的字节必须是int
    • 因为bytearray它操作的是单个字节
    • python没有byte这种类型, 但是byte都可以用int表示。
    • 但并不是所有的int可以
  • int必须在0 ~ 256这个范围内, 即8位无符号整数。例如b.append(10000000000)就会报错
In [16]: b = b‘abc‘

In [17]: b[1] = b‘B‘    # 不可变的情况在这
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-77f7c5b425ec> in <module>()
----> 1 b[1] = b‘B‘

TypeError: ‘bytes‘ object does not support item assignment

In [176]: b = bytearray(b)

In [20]: b[1] = int(b‘B‘.hex(), 16)   # bytearray可变的地方

In [21]: b
Out[21]: bytearray(b‘aBc‘)

bytearray是可变的

bytes为什么需要一个可变的版本? 
    图片处理, 修改几个像素的时候, bytes无法原地修改, 如果一个图片3M修改1000次就需要3G的内存, bytearray为了针对这种场景的。大对象的二进制文件做一些原地处理。

str为什么没有一个可变版本?
    因为str没有那么大的对象,如果有, 可以先转换为bytearray, 然后再进行处理, 所以不需要。

相对于bytes来说, 多了insert, append, extend, pop, remove, clear, reverse原地修改的方法。
并且支持索引操作

In [23]: b.append(b‘b‘)   # insert, append, remove, count参数必须是int
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-23-ac0cb45348e8> in <module>()
----> 1 b.append(b‘b‘)

TypeError: an integer is required

为什么bytearray插入的字节必须是int
    因为bytearray它操作的是单个字节
    python没有byte这种类型, 但是byte都可以用int表示。
    但并不是所有的int可以

In [24]: b.append(10000000000000000000000000000000000000000000000000000000000000000000)   # int必须在0 ~ 256这个范围内, 即8位无符号整数。
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-24-2897620e98cd> in <module>()
----> 1 b.append(10000000000000000000000000000000000000000000000000000000000000000000)

ValueError: byte must be in range(0, 256)