传统上,Python对于“大尾数C布局中的数字”用处不大,而对于C来说则用不了太多。(如果要处理2字节,4字节或8字节的数字,那么
struct.unpack答案就是)
但是足够多的人厌倦了没有一种明显的方法可以做到这一点,Python
3.2添加了一种
int.from_bytes完全可以实现您想要的方法:
int.from_bytes(b, byteorder='big', signed=False)
不幸的是,如果您使用的是旧版本的Python,则没有此功能。那么,您有什么选择?(除了显而易见的一个:更新为3.2,或者更好的是3.4…)
首先,有您的代码。我认为
binascii.hexlify它是比esb更好的拼写方式
.enpre('hex'),因为“
enpre”对于字节串(相对于Unipre字符串)的方法似乎总是有些怪异,并且实际上已在Python
3中被淘汰了。但是,否则,似乎可读性强,对我来说很明显。而且它应该非常快-
是的,它必须创建一个中间字符串,但是它正在C中进行所有循环和算术运算(至少在CPython中),这通常比Python快一两个数量级。除非您
bytearray太大,以至于分配字符串本身都会很昂贵,否则我在这里不必担心性能。
或者,您可以循环执行。但这将更加冗长,至少在CPython中要慢得多。
您可以尝试消除一个隐式循环的显式循环,但是这样做的明显功能是
reduce,在社区中,这被视为非Python的—当然,这将需要为每个字节调用一个函数。
您可以展开循环,也
reduce可以将其分解为8个字节的块并进行循环
struct.unpack_from,或者通过做一个大的
struct.unpack('Q'*len(b)//8+ 'B' * len(b)%8)循环来进行循环,但这会使它的可读性大大降低,并且可能并没有那么快。
您可以使用NumPy…,但是如果您要大于64位或128位,则最终将所有内容都转换为Python对象。
因此,我认为您的答案是最好的选择。
以下是一些将其与最明显的手动转换进行比较的时间:
import binasciiimport functoolsimport numpy as npdef hexint(b): return int(binascii.hexlify(b), 16)def loop1(b): def f(x, y): return (x<<8)|y return functools.reduce(f, b, 0)def loop2(b): x = 0 for c in b: x <<= 8 x |= c return xdef numpily(b): n = np.array(list(b)) p = 1 << np.arange(len(b)-1, -1, -1, dtype=object) return np.sum(n * p)
In [226]: b = bytearray(range(256))In [227]: %timeit hexint(b)1000000 loops, best of 3: 1.8 µs per loopIn [228]: %timeit loop1(b)10000 loops, best of 3: 57.7 µs per loopIn [229]: %timeit loop2(b)10000 loops, best of 3: 46.4 µs per loopIn [283]: %timeit numpily(b)10000 loops, best of 3: 88.5 µs per loop
为了在Python 3.4中进行比较:
In [17]: %timeit hexint(b)1000000 loops, best of 3: 1.69 µs per loopIn [17]: %timeit int.from_bytes(b, byteorder='big', signed=False)1000000 loops, best of 3: 1.42 µs per loop
因此,您的方法仍然相当快……
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)