Python二进制序列类型(一)bytes与bytearray

Python实用教程_spiritx的博客-CSDN博客

Python中有一类特殊的对象称为字节类对象,可在多种二进制数据操作中使用,如图片、音频、视频数据,通过socket套接字发送数据,以及与C语言的API进行数据交互等等。

bytes 只负责以字节序列的形式(二进制形式)来存储数据,至于这些数据到底表示什么内容(字符串、数字、图片、音频等),完全由程序的解析方式决定。如果采用合适的字符编码方式(字符集),字节串可以恢复成字符串;反之亦然,字符串也可以转换成字节串。

说的更直白一点,bytes 只是简单地记录内存中的原始数据,至于如何使用这些数据,bytes 并不在意,你想怎么使用就怎么使用,bytes 并不约束你的行为。

包括所有 bytes、bytearray 和 array.array 对象,以及许多普通 memoryview 对象。

bytes

bytes 对象是由单个字节构成的不可变序列。

Bytes 本质是一串由 0 和 1 组成的二进制串,但为了显示方便,每八位划分为一组,然后按组显示。如果这八位正好是一个可打印的 ASCII 字符的编码,如 A、z、0、% 等,则显示该字符;如果不是,则显示十六进制。

由于许多主要二进制协议都基于 ASCII 文本编码,因此 bytes 对象提供了一些仅在处理 ASCII 兼容数据时可用,并且在许多特性上与字符串对象紧密相关的方法。

字节串(bytes)和字符串(string)的对比:

  • 字符串由若干个字符组成,以字符为单位进行操作;字节串由若干个字节组成,以字节为单位进行操作。
  • 字节串和字符串除了操作的数据单元不同之外,它们支持的所有方法都基本相同。
  • 字节串和字符串都是不可变序列,不能随意增加和删除数据。

字符串和 bytes 存在着千丝万缕的联系,我们可以通过字符串来创建 bytes 对象,或者说将字符串转换成 bytes 对象。有以下三种方法可以达到这个目的:

  • 如果字符串的内容都是 ASCII 字符,那么直接在字符串前面添加b前缀就可以转换成 bytes。
  • bytes 是一个类,调用它的构造方法,也就是 bytes(),可以将字符串按照指定的字符集转换成 bytes;如果不指定字符集,那么默认采用 UTF-8。
  • 字符串本身有一个 encode() 方法,该方法专门用来将字符串按照指定的字符集转换成对应的字节串;如果不指定字符集,那么默认采用 UTF-8。

创建bytes

创建bytes有多种方法,一种是通过bytes进行显示的声明和转换,一种是从其他对象生成或转换而来。

声明和定义bytes对象

语法:

class bytes([source[, encoding[, errors]]])

通过bytes()函数显示声明一个bytes类型

首先,表示 bytes 字面值的语法与字符串字面值的大致相同,只是添加了一个 b 前缀:

  • 单引号: b'同样允许嵌入 "双" 引号'
  • 双引号: b"仍然允许嵌入 '单' 引号"
  • 三重引号: b'''三重单引号'''b"""三重双引号"""

bytes 字面值中只允许 ASCII 字符(无论源代码声明的编码为何)。 任何超出 127 的二进制值必须使用相应的转义序列形式加入 bytes 字面值。

像字符串字面值一样,bytes 字面值也可以使用 r 前缀来禁用转义序列处理。

虽然 bytes 字面值和表示法是基于 ASCII 文本的,但 bytes 对象的行为实际上更像是不可变的整数序列,序列中的每个值的大小被限制为 0 <= x < 256 (如果违反此限制将引发 ValueError)。 这种限制是有意设计用以强调以下事实,虽然许多二进制格式都包含基于 ASCII 的元素,可以通过某些面向文本的算法进行有用的操作,但情况对于任意二进制数据来说通常却并非如此(盲目地将文本处理算法应用于不兼容 ASCII 的二进制数据格式往往将导致数据损坏)。

除了字面值形式,bytes 对象还可以通过其他几种方式来创建:

  • 指定长度的以零值填充的 bytes 对象: bytes(10)
  • 通过由整数组成的可迭代对象: bytes(range(20))
  • 通过缓冲区协议复制现有的二进制数据: bytes(obj)
>>> b'123'
b'123'
>>> b'一二三'
  File "<stdin>", line 1
    b'一二三'
          ^
SyntaxError: bytes can only contain ASCII literal characters

#大于 127 的字符建议使用 \xhh 表示。
>>> b'\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89'
b'\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89’

>>> bytes('一二三', 'utf-8')
b'\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89’

>>> '一二三'.encode()  # 或 '一二三'.encode('utf-8')
b'\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89’

>>> s = '这是一个中文字符串'
>>> b = s.encode('utf-8')
>>> print(b)
b'\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2'

从十六进制字符串转换

语法:

classmethod bytes.fromhex(string)

通过bytes的类方法将一个包含16进制数字串的string转换为bytes类型

由于两个十六进制数码精确对应一个字节,因此十六进制数是描述二进制数据的常用格式。 相应地,bytes 类型具有从此种格式读取数据的附加类方法。

方法返回一个解码给定字符串的 bytes 对象。 字符串必须由表示每个字节的两个十六进制数码构成,其中的 ASCII 空白符会被忽略。

>>>bytes.fromhex('2Ef0 F1f2  ')
b'.\xf0\xf1\xf2'

从一般字符串转换

语法:

str.encode(encoding='UTF-8',errors='strict')

参数:

  • encoding -- 要使用的编码,如"UTF-8"。
  • errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个UnicodeError。 其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。

返回编码后的字节串

如:

>>> str = "C语言中文网"
>>> str.encode()
b'C\xe8\xaf\xad\xe8\xa8\x80\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x91'

转换为其他类型

转换为十六进制字符串

语法格式:

hex([sep[, bytes_per_sep]])

可以将 bytes 对象转换为对应的十六进制表示.

返回一个字符串对象,该对象包含实例中每个字节的两个十六进制数字。

>>>b'\xf0\xf1\xf2'.hex()
‘f0f1f2'

#将字符转化为 GBK 编码:
#方法一:
>>> bytes('一二三', 'gbk').hex()
'd2bbb6fec8fd'

#方法二:
>>> '一二三'.encode('gbk').hex()
‘d2bbb6fec8fd'


#将 GBK 编码转化为字符 :
#方法一:
>>> str(bytes.fromhex('d2bbb6fec8fd'), 'gbk')
'一二三'

#方法二:
>>> bytes.fromhex('d2bbb6fec8fd').decode('gbk')
'一二三'

如果你希望令十六进制数字符串更易读,你可以指定单个字符分隔符作为 sep 形参包含于输出中。 默认情况下,该分隔符会放在每个字节之间。 第二个可选的 bytes_per_sep 形参控制间距。 正值会从右开始计算分隔符的位置,负值则是从左开始。

>>>value = b'\xf0\xf1\xf2'
>>>value.hex('-')
'f0-f1-f2'
>>>value.hex('_', 2)
'f0_f1f2'
>>>b'UUDDLRLRAB'.hex(' ', -4)
'55554444 4c524c52 4142'

由于 bytes 对象是由整数构成的序列(类似于元组),因此对于一个 bytes 对象 bb[0] 将为一个整数,而 b[0:1] 将为一个长度为 1 的 bytes 对象。 (这与文本字符串不同,索引和切片所产生的将都是一个长度为 1 的字符串)。

bytes 对象的表示使用字面值格式 (b'...'),因为它通常都要比像 bytes([46, 46, 46]) 这样的格式更好用。 你总是可以使用 list(b) 将 bytes 对象转换为一个由整数构成的列表。

转换为一般字符串 

语法格式:

bytes.decode(encoding='utf-8'errors='strict')

encoding为编码格式

返回解码为 str 的字节串。

errors 控制如何处理编码错误。

含意

'strict'

引发 UnicodeError (或其子类),这是默认的方案。 在 strict_errors() 中实现。

'ignore'

忽略错误格式的数据并且不加进一步通知就继续执行。 在 ignore_errors() 中实现。

'replace'

用一个替代标记来替换。 在编码时,使用 ? (ASCII 字符)。 在解码时,使用 � (U+FFFD,官方的 REPLACEMENT CHARACTER)。 在 replace_errors() 中实现。

'backslashreplace'

用反斜杠转义序列来替换。 在编码时,使用格式为 \xhh \uxxxx \Uxxxxxxxx 的 Unicode 码位十六进制表示形式。 在解码时,使用格式为 \xhh 的字节值十六进制表示形式。 在 backslashreplace_errors() 中实现。

'surrogateescape'

在解码时,将字节替换为 U+DC80 至 U+DCFF 范围内的单个代理代码。 当在编码数据时使用 'surrogateescape' 错误处理方案时,此代理将被转换回相同的字节。 

>>> str(b'\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89', 'utf-8')
'一二三'
>>> b'\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89'.decode() 
'一二三'

其他方法

查找和匹配方法

统计子串出现的次数

语法为:

bytes.count(sub[, start[, end]])

返回子序列 sub 在 [startend] 范围内非重叠出现的次数。 可选参数 start 与 end 会被解读为切片表示法。

如果 sub 为空,则返回字节串对象的长度加一.

a = b'abcabcabd'
print(a.count(b'')) #4
print(a.count(b'ab'))#3
匹配前缀

语法为:

bytes.startswith(prefix[, start[, end]])

如果二进制数据以指定的 prefix 开头则返回 True,否则返回 False。 prefix 也可以为由多个供查找的前缀构成的元组。 如果有可选项 start,将从所指定位置开始检查。 如果有可选项 end,将在所指定位置停止比较。

s = b'Apollo'
print(f"{s.startswith(b'Ap')=}")  #s.startswith(b'Ap')=True
#s.startswith('Ap')   #TypeError prefix必须是bytes类型

s = b'Apollo'
print(f"{s.startswith(b'po')=}")  #s.startswith(b'po')=False

s = b'Apollo'
print(f"{s.startswith(b'Apo')=}")  #s.startswith(b'Apo')=True
print(f"{s.startswith(b'Apo',1,4)=}")  #s.startswith(b'Apo',1,4)=False
匹配后缀

语法为:

bytes.endswith(suffix[, start[, end]])

如果二进制数据以指定的 suffix 结束则返回 True,否则返回 False。 suffix 也可以为由多个供查找的后缀构成的元组。 如果有可选项 start,将从所指定位置开始检查。 如果有可选项 end,将在所指定位置停止比较。

删除前缀

语法为:

bytes.removeprefix(prefix/)

如果二进制数据以 prefix 字符串开头,返回 bytes[len(prefix):]。 否则,返回原始二进制数据的副本:

>>>b'TestHook'.removeprefix(b'Test')
b'Hook'
>>>b'BaseTestCase'.removeprefix(b'Test')
b'BaseTestCase'

注意:此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变,后面的其他方法也基本是这样的,如果有特别的会进行单独说明。

删除后缀

语法:

bytes.removesuffix(suffix/)

如果二进制数据以 suffix 字符串结尾,并且 suffix 非空,返回 bytes[:-len(suffix)]。 否则,返回原始二进制数据的副本:

>>> b'demo.py'.removesuffix(b'.py')
b'demo'
>>> b'demo.py'.removesuffix(b'.cpp')
b'demo.py'
查找子串

语法:

bytes.find(sub[, start[, end]])

返回子序列 sub 在数据中被找到的最小索引,sub 包含于切片 s[start:end] 之内。 可选参数 start 与 end 会被解读为切片表示法。 如果 sub 未被找到则返回 -1

备注 find() 方法应该只在你需要知道 sub 所在位置时使用。 要检查 sub 是否为子串,请使用 in 操作符:

>>> b'py' in b'demo.py'
True

语法:

bytes.index(sub[, start[, end]])

类似于 find(),但在找不到子序列时会引发 ValueError。

>>> x = 0x32 
>>> b'1234'.index(bytes([x])) 
1 
从右查找子串

语法:

bytes.rfind(sub[, start[, end]])

返回子序列 sub 在序列内被找到的最大(最右)索引,这样 sub 将包含在 s[start:end] 当中。 可选参数 start 与 end 会被解读为切片表示法。 如果未找到则返回 -1

语法:

bytes.rindex(sub[, start[, end]])

类似于 rfind(),但在子序列 sub 未找到时会引发 ValueError。

拆分字节串

拆分为三元组

语法:

bytes.partition(sep)

在 sep 首次出现的位置拆分序列,返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身或其 bytearray 副本,以及分隔符之后的部分。 如果分隔符未找到,则返回的 3 元组中包含原序列以及两个空的 bytes 或 bytearray 对象。

语法:

bytes.rpartition(sep)

在 sep 最后一次出现的位置拆分序列,返回一个 3 元组,其中包含分隔符之前的部分,分隔符本身或其 bytearray 副本,以及分隔符之后的部分。 如果分隔符未找到,则返回的 3 元组中包含两个空的 bytes 或 bytearray 对象以及原序列的副本。

>>> b'demo.py'.rpartition(b'.')
(b'demo', b'.', b'py')
>>> b'demo.py'.partition(b'.')
(b'demo', b'.', b'py')
>>> b'demo.20230904.py'.rpartition(b'.')
(b'demo.20230904', b'.', b'py')
>>> b'demo.20230904.py'.partition(b'.')
(b'demo', b'.', b'20230904.py')

注意与patition()方法的差别,rpatition()并没有把返回序列的三个元素的顺序倒置过来,r体现的是获取sep的位置。

多元组拆分

语法:

 bytes.split(sep=Nonemaxsplit=- 1)

将二进制序列拆分为相同类型的子序列,使用 sep 作为分隔符。 如果给出了 maxsplit 且非负值,则最多进行 maxsplit 次拆分(因此,列表最多会有 maxsplit+1 个元素)。 如果 maxsplit 未指定或为 -1,则不限制拆分次数(进行所有可能的拆分)。

如果给出了 sep,则连续的分隔符不会被组合在一起而是被视为分隔空子序列 (例如 b'1,,2'.split(b',') 将返回 [b'1', b'', b'2'])。 sep 参数可能为一个多字节序列 (例如 b'1<>2<>3'.split(b'<>') 将返回 [b'1', b'2', b'3'])。 使用指定的分隔符拆分空序列将返回 [b''] 或 [bytearray(b'')],具体取决于被拆分对象的类型。

>>>b'1,2,3'.split(b',')
[b'1', b'2', b'3']
>>>b'1,2,3'.split(b',', maxsplit=1)
[b'1', b'2,3']
>>>b'1,2,,3,'.split(b',')
[b'1', b'2', b'', b'3', b'']

如果 sep 未指定或为 None,则会应用另一种拆分算法:连续的 ASCII 空白符会被视为单个分隔符,其结果将不包含序列开头或末尾的空白符。 因此,在不指定分隔符的情况下对空序列或仅包含 ASCII 空白符的序列进行拆分将返回 []

>>>b'1 2 3'.split()
[b'1', b'2', b'3']
>>>b'1 2 3'.split(maxsplit=1)
[b'1', b'2 3']
>>>b'   1   2   3   '.split()
[b'1', b'2', b'3']

语法:

 bytes.rsplit(sep=Nonemaxsplit=- 1)

将二进制序列拆分为相同类型的子序列,使用 sep 作为分隔符。 如果给出了 maxsplit,则最多进行 maxsplit 次拆分,从 最右边 开始。 如果 sep 未指定或为 None,任何只包含 ASCII 空白符的子序列都会被作为分隔符。 除了从右边开始拆分,rsplit() 的其他行为都类似于下文所述的 split()。

按行拆分

 bytes.splitlines(keepends=False)

返回由原二进制序列中各行组成的列表,在 ASCII 行边界符的位置拆分。结果列表中不包含换行符,除非给出了 keepends 且为真值。

Unix 的行结束约定 '\n'、Windows 的约定 '\r\n' 以及旧版 Macintosh 的约定 '\r'

不同于 split(),当给出了分隔符 sep 时,对于空字符串此方法将返回一个空列表,而末尾的换行不会令结果中增加额外的行:

>>>b"".split(b'\n'), b"Two lines\n".split(b'\n')
([b''], [b'Two lines', b''])
b"".splitlines(), b"One line\n".splitlines()
([], [b'One line'])

对齐

左对齐

语法:

bytes.ljust(width[, fillbyte])

返回原对象的副本,在长度为 width 的序列中靠左对齐。 使用指定的 fillbyte 填充空位(默认使用 ASCII 空格符)。 对于 bytes 对象,如果 width 小于等于 len(s) 则返回原序列的副本。

右对齐

语法:

bytes.rjust(width[, fillbyte])

返回原对象的副本,在长度为 width 的序列中靠右对齐。 使用指定的 fillbyte 填充空位(默认使用 ASCII 空格符)。 对于 bytes 对象,如果 width 小于等于 len(s) 则返回原序列的副本。

此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。

居中

语法: 

bytes.center(width[, fillbyte])

返回原对象的副本,在长度为 width 的序列内居中,使用指定的 fillbyte 填充两边的空位(默认使用 ASCII 空格符)。对于 bytes 对象,如果 width 小于等于 len(s) 则返回原序列的副本。

 去空格

去前(左)空格

语法:

bytes.lstrip([chars])

返回原序列的副本,移除指定的前导字节。 chars 参数为指定要移除字节值集合的二进制序列 —— 这个名称表明此方法通常是用于 ASCII 字符。 如果省略或为 None,则 chars 参数默认移除 ASCII 空白符。 chars 参数并非指定单个前缀;而是会移除参数值的所有组合:

>>> b'  www'.lstrip()
b'www'
>>> b'abc-abc-abcd'.lstrip(b'abcd')
b'-abc-abcd'
去后(右)空格

语法:

bytes.rstrip([chars])

返回原序列的副本,移除指定的末尾字节。 chars 参数为指定要移除字节值集合的二进制序列 —— 这个名称表明此方法通常是用于 ASCII 字符。 如果省略或为 None,则 chars 参数默认移除 ASCII 空白符。 chars 参数并非指定单个后缀;而是会移除参数值的所有组合:

去前后空格

bytes.strip([chars])

返回原序列的副本,移除指定的开头和末尾字节。 chars 参数为指定要移除字节值集合的二进制序列 —— 这个名称表明此方法通常是用于 ASCII 字符。 如果省略或为 None,则 chars 参数默认移除 ASCII 空白符。 chars 参数并非指定单个前缀或后缀;而是会移除参数值的所有组合:

>>>b'   spacious   '.strip()
b'spacious'
>>>b'www.example.com'.strip(b'cmowz.')
b'example'

字符类型判断

字母数字串

bytes.isalnum()

如果序列中所有字节都是字母类 ASCII 字符或 ASCII 十进制数码并且序列非空则返回 True ,否则返回 False 。 字母类 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' 中的字符。 ASCII 十进制数码就是字节值包含在序列 b'0123456789' 中的字符。

>>>b'ABCabc1'.isalnum()
True
>>>b'ABC abc1'.isalnum()
False
字母串

bytes.isalpha()

如果序列中所有字节都是字母类 ASCII 字符并且序列不非空则返回 True ,否则返回 False 。 字母类 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' 中的字符。

>>>b'ABCabc'.isalpha()
True
>>>b'ABCabc1'.isalpha()
False
ASCII串

bytes.isascii()

如果序列为空或序列中所有字节都是 ASCII 字节则返回 True ,否则返回 False 。 ASCII 字节的取值范围是 0-0x7F。

数字串

bytes.isdigit()

如果序列中所有字节都是 ASCII 十进制数码并且序列非空则返回 True ,否则返回 False 。 ASCII 十进制数码就是字节值包含在序列 b'0123456789' 中的字符。

小写串

bytes.islower()

如果序列中至少有一个小写的 ASCII 字符并且没有大写的 ASCII 字符则返回 True ,否则返回 False 。

大写串

bytes.isupper()

如果序列中至少有一个大写字母 ASCII 字符并且没有小写 ASCII 字符则返回 True ,否则返回 False 。

空格串

bytes.isspace()

如果序列中所有字节都是 ASCII 空白符并且序列非空则返回 True ,否则返回 False 。 ASCII 空白符就是字节值包含在序列 b' \t\n\r\x0b\f' (空格, 制表, 换行, 回车, 垂直制表, 进纸) 中的字符。

标题串

bytes.istitle()

如果序列为 ASCII 标题大小写形式并且序列非空则返回 True ,否则返回 False 。

其中每个单词以一个大写 ASCII 字符为开头,其余字母为小写。 不区别大小写的字节值将保持原样不变。

替换和转换

转为小写

 bytes.lower()

返回原序列的副本,其所有大写 ASCII 字符均转换为对应的小写形式。

转为大写

bytes.upper()

返回原序列的副本,其所有小写 ASCII 字符均转换为对应的大写形式。

大小写互换

bytes.swapcase()

返回原序列的副本,其所有小写 ASCII 字符均转换为对应的大写形式,反之亦反。

>>>b'Hello World'.swapcase()
b'hELLO wORLD'
替换

bytes.replace(oldnew[, count])

返回序列的副本,其中出现的所有子序列 old 都将被替换为 new。 如果给出了可选参数 count,则只替换前 count 次出现。

注意:此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。

首字母大写

bytes.capitalize()

返回原序列的副本,其中每个字节将都将被解读为一个 ASCII 字符,并且第一个字节的字符大写而其余的小写。 非 ASCII 字节值将保持原样不变。

制表符替换为空格

 bytes.expandtabs(tabsize=8)

返回序列的副本,其中所有的 ASCII 制表符会由一个或多个 ASCII 空格替换,具体取决于当前列位置和给定的制表符宽度。 每 tabsize 个字节设为一个制表位(默认值 8 时设定的制表位在列 0, 8, 16 依次类推)。 要展开序列,当前列位置将被设为零并逐一检查序列中的每个字节。 如果字节为 ASCII 制表符 (b'\t'),则并在结果中插入一个或多个空格符,直到当前列等于下一个制表位。 (制表符本身不会被复制。) 如果当前字节为 ASCII 换行符 (b'\n') 或回车符 (b'\r'),它会被复制并将当前列重设为零。 任何其他字节会被不加修改地复制并将当前列加一,不论该字节值在被打印时会如何显示:

>>>b'01\t012\t0123\t01234'.expandtabs()
b'01      012     0123    01234'
>>>b'01\t012\t0123\t01234'.expandtabs(4)
b'01  012 0123    01234'

按码表转换

static bytes.maketrans(fromto)

此静态方法返回一个可用于 bytes.translate() 的转换对照表,它将把 from 中的每个字符映射为 to 中相同位置上的字符;from 与 to 必须都是 字节类对象 并且具有相同的长度。

bytes.translate(table/delete=b'')

返回原 bytes 或 bytearray 对象的副本,移除其中所有在可选参数 delete 中出现的 bytes,其余 bytes 将通过给定的转换表进行映射,该转换表必须是长度为 256 的 bytes 对象。

你可以使用 bytes.maketrans() 方法来创建转换表。

>>>b'read this short text'.translate(None, b'aeiou')
b'rd ths shrt txt'

转换为标题串

bytes.title()

返回原二进制序列的标题版本,其中每个单词以一个大写 ASCII 字符为开头,其余字母为小写。 不区别大小写的字节值将保持原样不变。

该算法使用一种简单的与语言无关的定义,将连续的字母组合视为单词。 该定义在多数情况下都很有效,但它也意味着代表缩写形式与所有格的撇号也会成为单词边界,这可能导致不希望的结果:

>>>b"they're bill's friends from the UK".title()
b"They'Re Bill'S Friends From The Uk"

可以使用正则表达式来构建针对撇号的特别处理:

>>>import re
>>>def titlecase(s):
    return re.sub(rb"[A-Za-z]+('[A-Za-z]+)?",
                  lambda mo: mo.group(0)[0:1].upper() +
                             mo.group(0)[1:].lower(),
                  s)

>>>titlecase(b"they're bill's friends.")
b"They're Bill's Friends."

填充

bytes.zfill(width)

返回原序列的副本,在左边填充 b'0' 数码使序列长度为 width。 正负值前缀 (b'+'/ b'-') 的处理方式是在正负符号 之后 填充而非在之前。 对于 bytes 对象,如果 width 小于等于 len(seq) 则返回原序列。

连接

bytes.join(iterable)

返回一个由 iterable 中的二进制数据序列拼接而成的 bytes 或 bytearray 对象。 如果 iterable 中存在任何非 字节类对象 包括存在 str 对象值则会引发 TypeError。 提供该方法的 bytes 或 bytearray 对象的内容将作为元素之间的分隔。

bytearray

bytearray 对象是 bytes 对象的可变对应物。

class bytearray([source[, encoding[, errors]]])

bytearray 对象没有专属的字面值语法,它们总是通过调用构造器来创建:

  • 创建一个空实例: bytearray()
  • 创建一个指定长度的以零值填充的实例: bytearray(10)
  • 通过由整数组成的可迭代对象: bytearray(range(20))
  • 通过缓冲区协议复制现有的二进制数据: bytearray(b'Hi!')

由于 bytearray 对象是可变的,该对象除了 bytes 中所描述的 共有操作之外,还支持 可变 序列操作。

可选形参 source 可以用不同的方式来初始化数组:

  • 如果是一个 string,您必须提供 encoding 参数(errors 参数仍是可选的);bytearray() 会使用 str.encode() 方法来将 string 转变成 bytes。
  • 如果是一个 integer,会初始化大小为该数字的数组,并使用 null 字节填充。
  • 如果是一个遵循 缓冲区接口 的对象,该对象的只读缓冲区将被用来初始化字节数组。
  • 如果是一个 iterable 可迭代对象,它的元素的范围必须是 0 <= x < 256 的整数,它会被用作数组的初始内容。
  • 如果没有实参,则创建大小为 0 的数组。

bytes的方法,bytearray都支持,用法也一致。

>>> a = bytearray(3)            # 创建一个长度为 3, 元素值为 0 的 bytearray
>>> a
bytearray(b'\x00\x00\x00')
>>> a[0] = 97; a[1] = 255       # 修改数字元素的值
>>> a
bytearray(b'a\xff\x00')
>>> a.append(65)                # 追加一个元素到末尾
>>> a
bytearray(b'a\xff\x00A')
>>> 
>>> a = bytearray("abc你好", "utf-8")    # 编码字符串创建 bytearray
>>> a
bytearray(b'abc\xe4\xbd\xa0\xe5\xa5\xbd')
>>> 
>>> a = bytearray([1, 2, 3, 65, 97])    # 把整数列表中的各元素串起来转换为 bytearray
>>> a
bytearray(b'\x01\x02\x03Aa')
>>> 
>>> a = bytearray(b"abc123")            # 根据 bytes 序列创建 bytearray
>>> a
bytearray(b'abc123')

bytearray独有的方法:

追加一个元素

bytearray.append(item: int)

添加一个元素到末尾, 值为 [0, 255] 区间内的整数

# 创建一个二进制串,并赋值
b = bytearray([0x44, 0x4C, 0x4a, 0x26])
print(b)         # 输出对应ASCII字符串:bytearray(b'DLJ&')

# 添加一个元素
b.append(0x3A)
print(b)        # 输出对应ASCII字符串:bytearray(b'DLJ&:')

# 创建一个8字节空间,赋空值
b = bytearray(8)
print(len(b))    # 输出 --> 8

# 给b设置值
b[0] = 0x44
b[1] = 0x4d
print(b)        # bytearray(b'DM\x00\x00\x00\x00\x00\x00')

# 以字符串创建一个二进制
b = bytearray(b'abc')
# 修改字符串值
b[1] = ord('R')
print(b)         # bytearray(b'aRc')

# 通过16进制字符串构建二进制
b = bytearray.fromhex('444c')
print(b)         # bytearray(b'DL')

# 二进制字符串转换为int,一个int为4字节,需要通过struct模块转换
import struct
b = bytearray([0x01, 0x02, 0x03, 0x04])
print(struct.unpack('i', b))     # 输出(67305985,)

参入一个元素

bytearray.insert(index: int, item: int)

在 index 位置插入一个元素, 值为 [0, 255] 区间内的整数

追加可迭代对象

bytearray.extend(iterable)

把可迭代对象的所有元素依次添加到数组的末尾,迭代元素的值必须为 [0, 255] 区间内的整数

移除一个元素

bytearray.remove(item: int)

移除一个元素, 从左到右查找

弹出最后一个元素

bytearray.pop(index: int = -1)

移除并返回指定位置元素, 默认是最后一个

my_array = bytearray([1, 2, 3, 4, 5])
my_array.append(6)
my_array.extend([7, 8, 9])
my_array.insert(0, 0)
my_array.pop(3)
my_array.remove(4)
my_array.reverse()
print(my_array)

bytearray(b'[9, 8, 7, 6, 5, 3, 2, 1, 0')

字节串反转

bytearray.reverse()

反转所有数组元素

# 字节对象
b = bytes([1, 2, 3, 4, 5])

# 反向迭代器
reversed_b = reversed(b)

# 反向字节序列
reversed_bytes = bytes(reversed_b)

print(reversed_bytes)

#b'\x05\x04\x03\x02\x01'

拷贝副本

bytearray.copy()

复制数组的内容, 创建其副本返回

清除元素

bytearray.clear()

清空数组内的所有元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值