包格式字符串中的自动重复标志

发布于 2024-12-11 11:24:59 字数 279 浏览 0 评论 0原文

在 php 中,unpack() 有“*”标志,表示“重复此格式直到输入结束”。例如,打印 97, 98, 99

$str = "abc";
$b = unpack("c*", $str);
print_r($b);

python 中有类似的东西吗?当然,我可以这样做

str = "abc"
print struct.unpack("b" * len(str), str)

,但我想知道是否有更好的方法。

In php, unpack() has the "*" flag which means "repeat this format until the end of input". For example, this prints 97, 98, 99

$str = "abc";
$b = unpack("c*", $str);
print_r($b);

Is there something like this in python? Of course, I can do

str = "abc"
print struct.unpack("b" * len(str), str)

but I'm wondering if there is a better way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

魂ガ小子 2024-12-18 11:24:59

在Python 3.4及更高版本中,您可以使用新函数 struct .iter_unpack

struct.iter_unpack(fmt, buffer)

根据格式字符串fmt从缓冲区buffer中迭代解包。该函数返回一个迭代器,它将从缓冲区读取相同大小的块,直到其所有内容都被消耗。缓冲区的大小(以字节为单位)必须是格式所需大小的倍数,如 calcsize() 所反映的。

每次迭代都会生成一个由格式字符串指定的元组。

假设我们要使用重复格式字符串 '<2sc'(2 个字符后跟一个字符)解压数组 b'\x01\x02\x03'*3字符,重复直到完成)。

使用iter_unpack,您可以执行以下操作:

>>> import struct
>>> some_bytes = b'\x01\x02\x03'*3
>>> fmt = '<2sc'
>>> 
>>> tuple(struct.iter_unpack(fmt, some_bytes))
((b'\x01\x02', b'\x03'), (b'\x01\x02', b'\x03'), (b'\x01\x02', b'\x03'))

如果您想取消嵌套此结果,可以使用itertools.chain.from_iterable

>>> from itertools import chain
>>> tuple(chain.from_iterable(struct.iter_unpack(fmt, some_bytes)))
(b'\x01\x02', b'\x03', b'\x01\x02', b'\x03', b'\x01\x02', b'\x03')

当然,您可以使用嵌套理解来完成同样的事情。

>>> tuple(x for subtuple in struct.iter_unpack(fmt, some_bytes) for x in subtuple)
(b'\x01\x02', b'\x03', b'\x01\x02', b'\x03', b'\x01\x02', b'\x03')

In Python 3.4 and later, you can use the new function struct.iter_unpack.

struct.iter_unpack(fmt, buffer)

Iteratively unpack from the buffer buffer according to the format string fmt. This function returns an iterator which will read equally-sized chunks from the buffer until all its contents have been consumed. The buffer’s size in bytes must be a multiple of the size required by the format, as reflected by calcsize().

Each iteration yields a tuple as specified by the format string.

Let's say we want to unpack the array b'\x01\x02\x03'*3 with the repeating format string '<2sc' (2 characters followed by a single character, repeat until done).

With iter_unpack, you can do the following:

>>> import struct
>>> some_bytes = b'\x01\x02\x03'*3
>>> fmt = '<2sc'
>>> 
>>> tuple(struct.iter_unpack(fmt, some_bytes))
((b'\x01\x02', b'\x03'), (b'\x01\x02', b'\x03'), (b'\x01\x02', b'\x03'))

If you want to un-nest this result, you can do so with itertools.chain.from_iterable.

>>> from itertools import chain
>>> tuple(chain.from_iterable(struct.iter_unpack(fmt, some_bytes)))
(b'\x01\x02', b'\x03', b'\x01\x02', b'\x03', b'\x01\x02', b'\x03')

Of course, you could just employ a nested comprehension to do the same thing.

>>> tuple(x for subtuple in struct.iter_unpack(fmt, some_bytes) for x in subtuple)
(b'\x01\x02', b'\x03', b'\x01\x02', b'\x03', b'\x01\x02', b'\x03')
空城仅有旧梦在 2024-12-18 11:24:59

struct.unpack 中没有内置这样的工具,但可以定义这样的函数:

import struct

def unpack(fmt, astr):
    """
    Return struct.unpack(fmt, astr) with the optional single * in fmt replaced with
    the appropriate number, given the length of astr.
    """
    # http://stackoverflow.com/a/7867892/190597
    try:
        return struct.unpack(fmt, astr)
    except struct.error:
        flen = struct.calcsize(fmt.replace('*', ''))
        alen = len(astr)
        idx = fmt.find('*')
        before_char = fmt[idx-1]
        n = (alen-flen)/struct.calcsize(before_char)+1
        fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
        return struct.unpack(fmt, astr)

print(unpack('b*','abc'))
# (97, 98, 99)

There is no such facility built into struct.unpack, but it is possible to define such a function:

import struct

def unpack(fmt, astr):
    """
    Return struct.unpack(fmt, astr) with the optional single * in fmt replaced with
    the appropriate number, given the length of astr.
    """
    # http://stackoverflow.com/a/7867892/190597
    try:
        return struct.unpack(fmt, astr)
    except struct.error:
        flen = struct.calcsize(fmt.replace('*', ''))
        alen = len(astr)
        idx = fmt.find('*')
        before_char = fmt[idx-1]
        n = (alen-flen)/struct.calcsize(before_char)+1
        fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
        return struct.unpack(fmt, astr)

print(unpack('b*','abc'))
# (97, 98, 99)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文