Struct.unpack和字节对象的长度

3 投票
2 回答
5983 浏览
提问于 2025-04-18 12:14

我有以下代码(data是一个字节对象):

    v = sum(struct.unpack('!%sH' % int(len(data)/2), data))

让我感到困惑的是格式字符串中的%sH和% int(len(data)/2

这部分代码到底是怎么工作的?字节对象的长度是什么?这到底是在求什么的和呢?

2 个回答

1

你的代码是怎么工作的:

  • 你在解析 data 的字节结构
    • struct.unpack 用一个字符串来告诉你想要解析的数据的字节格式
    • 根据这个格式,struct.unpack 会返回一个可迭代的解析结果。
  • 然后你对这个可迭代的结果进行求和。

字节格式化

为了解析你传入的数据,你需要创建一个 字符串 来告诉 Python 数据的格式。具体来说,%sH 这个部分是用来表示 这个数量的无符号短整型,然后你可以格式化它,说明你想要的 unsigned short 的确切数量。

在这个例子中,数量是:

int(len(data) / 2)

因为一个 unsigned short 通常是 2 个字节宽。

5

假设你有一个字节串 data,比如:

>>> data = b'\x01\x02\x03\x04'
>>> data
'\x01\x02\x03\x04'

这个字节串的长度就是里面的字节(或字符)数量:

>>> len(data)
4

所以这段代码和你的代码是等价的:

>>> import struct
>>> struct.unpack('!2H', data)
(258, 772)

这段代码告诉 struct 模块使用以下的 格式字符

  • ! - 使用网络(大端)模式
  • 2H - 解包两个无符号短整型(每个16位)

这样就会返回两个整数,这两个整数对应你提供的数据:

>>> '%04x' % 258
'0102'
>>> '%04x' % 772
'0304'

你的代码的作用就是自动计算出无符号短整型的数量

>>> struct.unpack('!%sH' % int(len(data)/2), data)
(258, 772)

不过,int 转换其实是多余的,而且不应该使用 %s 这个占位符,因为它是用来替换字符串的:

>>> struct.unpack('!%dH' % (len(data)/2), data)
(258, 772)

所以解包的结果会返回两个整数,这两个整数是从字节串中解包出的两个无符号短整型的值。然后,求和操作会返回这两个整数的和:

>>> sum(struct.unpack('!%dH' % (len(data)/2), data))
1030

撰写回答