python bytearrays在哪里使用?

Lel*_*uge 44 python types

我最近遇到了bytearray在python中调用的dataType .有人可以提供需要字节数组的场景吗?

Sin*_*ion 50

A bytearray非常类似于常规python字符串(str在python2.x中,bytes在python3中),但有一个重要区别,而字符串是不可变的,bytearrays是可变的,有点像list单个字符串.

这很有用,因为某些应用程序使用字节序列的方式与不可变字符串表现不佳.当你在大块内存中间进行大量的小改动时,如在数据库引擎或图像库中,字符串的表现非常差; 因为你必须复制整个(可能很大的)字符串. bytearrays的优点是可以在不首先复制内存的情况下进行这种更改.

但这个特殊情况实际上更多的是例外,而不是规则.大多数用途涉及比较字符串或字符串格式.对于后者,无论如何通常都有副本,因此可变类型不会提供任何优势,而对于前者,由于不可变字符串不能更改,您可以计算hash字符串的一个并将其作为按顺序比较每个字节的快捷方式进行比较,这几乎总是一场大胜利; 所以它是默认的不可变类型(strbytes); 并且bytearray是例外,当你需要它的特殊功能.

  • 此外,bytearray允许人们将其元素作为0-256范围内的数字或one-char字符串进行操作,就像在C and dother派生语言中完成一样.在这方面它非常灵活. (5认同)

Lel*_*uge 48

这个答案已被无可挽回地从这里扯下

示例1:从片段组装消息

假设您正在编写一些在套接字连接上接收大消息的网络代码.如果您了解套接字,则您知道该recv()操作不会等待所有数据到达.相反,它只返回系统缓冲区中当前可用的内容.因此,要获取所有数据,您可能会编写如下代码:

# remaining = number of bytes being received (determined already)
msg = b""
while remaining > 0:
    chunk = s.recv(remaining)    # Get available data
    msg += chunk                 # Add it to the message
    remaining -= len(chunk)  
Run Code Online (Sandbox Code Playgroud)

这段代码的唯一问题是连接(+=)具有可怕的性能.因此,Python 2中的常见性能优化是收集列表中的所有块并在完成后执行连接.像这样:

# remaining = number of bytes being received (determined already)
msgparts = []
while remaining > 0:
    chunk = s.recv(remaining)    # Get available data
    msgparts.append(chunk)       # Add it to list of chunks
    remaining -= len(chunk)  
msg = b"".join(msgparts)          # Make the final message
Run Code Online (Sandbox Code Playgroud)

现在,这是使用以下的第三种解决方案bytearray:

# remaining = number of bytes being received (determined already)
msg = bytearray()
while remaining > 0:
    chunk = s.recv(remaining)    # Get available data
    msg.extend(chunk)            # Add to message
    remaining -= len(chunk)  
Run Code Online (Sandbox Code Playgroud)

注意bytearray版本是如何干净的.您不会在列表中收集零件,也不会在最后执行该神秘连接.尼斯.

当然,最大的问题是它是否有效.为了测试这个,我首先列出了一个像这样的小字节片段列表:

chunks = [b"x"*16]*512
Run Code Online (Sandbox Code Playgroud)

然后我使用timeit模块比较以下两个代码片段:

# Version 1
msgparts = []
for chunk in chunks:
    msgparts.append(chunk)
msg = b"".join(msgparts)
Run Code Online (Sandbox Code Playgroud)

#Version 2
msg = bytearray()
for chunk in chunks:
    msg.extend(chunk)
Run Code Online (Sandbox Code Playgroud)

测试时,代码的版本1运行在99.8s,而版本2运行在116.6s(+=相比之下,使用串联的版本需要230.3s).因此,虽然执行连接操作仍然更快,但它只会快16%左右.就个人而言,我认为该bytearray版本的清洁编程可能会弥补它.

示例2:二进制记录打包

这个例子在最后一个例子上略有不同.假设你有一个庞大的整数(x,y)坐标的Python列表.类似这样的事情: points = [(1,2),(3,4),(9,10),(23,14),(50,90),...] 现在,假设您需要将该数据写为二进制编码文件,该文件由32位整数长度组成,然后将每个点打包成一对32位整数.一种方法是使用这样的struct模块:

import struct
f = open("points.bin","wb")
f.write(struct.pack("I",len(points)))
for x,y in points:
    f.write(struct.pack("II",x,y))
f.close()
Run Code Online (Sandbox Code Playgroud)

此代码的唯一问题是它执行大量小write()操作.另一种方法是将所有内容打包成一个bytearray并且最后只执行一次写入.例如:

import struct
f = open("points.bin","wb")
msg = bytearray()
msg.extend(struct.pack("I",len(points))
for x,y in points:
    msg.extend(struct.pack("II",x,y))
f.write(msg)
f.close()
Run Code Online (Sandbox Code Playgroud)

果然,使用的版本bytearray运行得更快.在一个涉及100000点列表的简单时序测试中,它运行的时间大约是创建大量小写的版本的一半.

例3:字节值的数学处理

bytearrays将自身表示为整数数组的事实使得执行某些类型的计算变得更容易.在最近的嵌入式系统项目中,我使用Python通过串行端口与设备通信.作为通信协议的一部分,所有消息都必须使用纵向冗余校验(LRC)字节进行签名.通过对所有字节值进行XOR来计算LRC.Bytearrays使这种计算变得容易.这是一个版本:

message = bytearray(...)     # Message already created
lrc = 0
for b in message:
    lrc ^= b
message.append(lrc)          # Add to the end of the message
Run Code Online (Sandbox Code Playgroud)

这是一个可以提高你的工作安全性的版本: message.append(functools.reduce(lambda x,y:x^y,message)) 这里的Python 2中没有bytearrays的计算相同:

message = "..."       # Message already created
lrc = 0
for b in message:
    lrc ^= ord(b)
message += chr(lrc)        # Add the LRC byte
Run Code Online (Sandbox Code Playgroud)

就个人而言,我喜欢这个bytearray版本.没有必要使用ord(),您只需将结果附加到消息的末尾而不是使用串联.

这是另一个可爱的例子.假设你想bytearray通过一个简单的XOR密码运行一个.这是一个单行代码:

>>> key = 37
>>> message = bytearray(b"Hello World")
>>> s = bytearray(x ^ key for x in message)
>>> s
bytearray(b'm@IIJ\x05rJWIA')
>>> bytearray(x ^ key for x in s)
bytearray(b"Hello World")
>>> 
Run Code Online (Sandbox Code Playgroud)

是演示文稿的链接

  • 他抄袭你,你抄袭他还是你抄袭自己?:) http://dabeaz.blogspot.com/2010/01/few-useful-bytearray-tricks.html (2认同)

And*_*ron 5

如果您查看文档bytearray,它会说:

返回一个新的字节数组.bytearray类型是0 <= x <256范围内的可变整数序列.

相比之下,文档bytes说:

返回一个新的"bytes"对象,它是一个不可变的整数序列,范围为0 <= x <256. bytes是bytearray的不可变版本 - 它具有相同的非变异方法和相同的索引和切片行为.

如您所见,主要区别在于可变性.str"更改"字符串的方法实际上返回一个具有所需修改的新字符串.而bytearray改变序列的方法实际上改变了序列.

bytearray如果您正在通过其二进制表示编辑大对象(例如图像的像素缓冲区),并且您希望就地进行修改以提高效率,则更倾向于使用.