如何在python中将字符串转换为int?
这样说:'y\xcc\xa6\xbb'
我想出了一个聪明/愚蠢的方法:
sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))
我知道必须有内置或标准库中的内容才能更简单地执行此操作...
这与你可以使用int(xxx,16)的converting a string of hex digits不同,而是我想转换一串实际的字节值。
更新:
我有点像詹姆斯的回答好一点,因为它不需要导入另一个模块,但Greg的方法更快:
>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244
我的hacky方法:
>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943
进一步更新:
有人在评论中询问导入另一个模块的问题是什么。好吧,导入模块不一定便宜,看看:
>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371
包括导入模块的成本几乎抵消了此方法的所有优点。我相信这只会包括在整个基准测试中导入一次的费用;看看每次强迫它重装时会发生什么:
>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794
毋庸置疑,如果您在每次导入时执行大量此方法的执行,那么这个问题就会成比例地减少。它也可能是i / o成本而不是cpu,因此它可能取决于特定机器的容量和负载特性。
答案 0 :(得分:274)
在Python 3.2及更高版本中,使用
>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='big')
2043455163
或
>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='little')
3148270713
根据字节字符串的endianness。
这也适用于任意长度的字节串整数,并且通过指定signed=True
适用于二进制补码有符号整数。请参阅docs for from_bytes
。
答案 1 :(得分:102)
您也可以使用struct模块执行此操作:
>>> struct.unpack("<L", "y\xcc\xa6\xbb")[0]
3148270713L
答案 2 :(得分:66)
正如Greg所说,如果你正在处理二进制值,你可以使用struct,但是如果你只有一个“十六进制数”但是以字节格式,你可能只想将其转换为:
s = 'y\xcc\xa6\xbb'
num = int(s.encode('hex'), 16)
......这与:
相同num = struct.unpack(">L", s)[0]
...除了它适用于任意数量的字节。
答案 3 :(得分:7)
我使用以下函数在int,hex和bytes之间转换数据。
def bytes2int(str):
return int(str.encode('hex'), 16)
def bytes2hex(str):
return '0x'+str.encode('hex')
def int2bytes(i):
h = int2hex(i)
return hex2bytes(h)
def int2hex(i):
return hex(i)
def hex2int(h):
if len(h) > 1 and h[0:2] == '0x':
h = h[2:]
if len(h) % 2:
h = "0" + h
return int(h, 16)
def hex2bytes(h):
if len(h) > 1 and h[0:2] == '0x':
h = h[2:]
if len(h) % 2:
h = "0" + h
return h.decode('hex')
来源:http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html
答案 4 :(得分:6)
import array
integerValue = array.array("I", 'y\xcc\xa6\xbb')[0]
警告:以上内容是特定于平台的。 “I”说明符和string-&gt; int转换的字节顺序都取决于您的特定Python实现。但是如果你想一次转换许多整数/字符串,那么数组模块会很快完成它。
答案 5 :(得分:5)
在Python 2.x中,您可以将格式说明符<B
用于无符号字节,将<b
用于带有struct.unpack
/ struct.pack
的带符号字节。
E.g:
让x
= '\xff\x10\x11'
data_ints = struct.unpack('<' + 'B'*len(x), x) # [255, 16, 17]
和
data_bytes = struct.pack('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11'
需要*
!
有关格式说明符的列表,请参阅 https://docs.python.org/2/library/struct.html#format-characters。
答案 6 :(得分:2)
>>> reduce(lambda s, x: s*256 + x, bytearray("y\xcc\xa6\xbb"))
2043455163
测试1:逆:
>>> hex(2043455163)
'0x79cca6bb'
测试2:字节数&gt; 8:
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAA"))
338822822454978555838225329091068225L
测试3:增加一:
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAB"))
338822822454978555838225329091068226L
测试4:附加一个字节,说'A':
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))
86738642548474510294585684247313465921L
测试5:除以256:
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))/256
338822822454978555838225329091068226L
结果等于测试4的结果,如预期的那样。
答案 7 :(得分:1)
int.from_bytes是最佳解决方案。 &#34; struct.unpack&#34;解决方案需要一个字符串,因此它不适用于字节数组。 这是另一种解决方案:
def bytes2int( tb, order='big'):
if order == 'big': seq=[0,1,2,3]
elif order == 'little': seq=[3,2,1,0]
i = 0
for j in seq: i = (i<<8)+tb[j]
return i
hex(bytes2int([0x87,0x65,0x43,0x21]))返回&#39; 0x87654321&#39;。
它处理大和小的字节序,并且很容易修改为8个字节
答案 8 :(得分:1)
如上所述,使用 struct 的unpack
功能是一种很好的方法。如果您想实现自己的功能,还有另一种解决方案:
def bytes_to_int(bytes):
result = 0
for b in bytes:
result = result * 256 + int(b)
return result
答案 9 :(得分:0)
我正在努力寻找可在Python 2.x下工作的任意长度字节序列的解决方案。最后我写了这个,它有点hacky因为它执行字符串转换,但它有效。
def signedbytes(data):
"""Convert a bytearray into an integer, considering the first bit as
sign. The data must be big-endian."""
negative = data[0] & 0x80 > 0
if negative:
inverted = bytearray(~d % 256 for d in data)
return -signedbytes(inverted) - 1
encoded = str(data).encode('hex')
return int(encoded, 16)
此功能有两个要求:
输入data
必须是bytearray
。你可以这样调用这个函数:
s = 'y\xcc\xa6\xbb'
n = signedbytes(s)
数据需要是大端的。如果你有一个小端值,你应该先反转它:
n = signedbytes(s[::-1])
当然,只有在需要任意长度时才应该使用它。否则,坚持使用更多标准方法(例如struct
)。
答案 10 :(得分:0)
一种使用array.array的相当快的方法,我已经使用了一段时间:
预定义变量:
offset = 0
size = 4
big = True # endian
arr = array('B')
arr.fromstring("\x00\x00\xff\x00") # 5 bytes (encoding issues) [0, 0, 195, 191, 0]
到int :(读)
val = 0
for v in arr[offset:offset+size][::pow(-1,not big)]: val = (val<<8)|v
来自int :(写)
val = 16384
arr[offset:offset+size] = \
array('B',((val>>(i<<3))&255 for i in range(size)))[::pow(-1,not big)]
虽然这些速度可能会更快。
编辑:
对于某些数字,这是一项性能测试(Anaconda 2.3.0),与reduce()
相比,显示稳定的读取平均值:
========================= byte array to int.py =========================
5000 iterations; threshold of min + 5000ns:
______________________________________code___|_______min______|_______max______|_______avg______|_efficiency
⣿⠀⠀⠀⠀⡇⢀⡀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⡀⠀⢰⠀⠀⠀⢰⠀⠀⠀⢸⠀⠀⢀⡇⠀⢀⠀⠀⠀⠀⢠⠀⠀⠀⠀⢰⠀⠀⠀⢸⡀⠀⠀⠀⢸⠀⡇⠀⠀⢠⠀⢰⠀⢸⠀
⣿⣦⣴⣰⣦⣿⣾⣧⣤⣷⣦⣤⣶⣾⣿⣦⣼⣶⣷⣶⣸⣴⣤⣀⣾⣾⣄⣤⣾⡆⣾⣿⣿⣶⣾⣾⣶⣿⣤⣾⣤⣤⣴⣼⣾⣼⣴⣤⣼⣷⣆⣴⣴⣿⣾⣷⣧⣶⣼⣴⣿⣶⣿⣶
val = 0 \nfor v in arr: val = (val<<8)|v | 5373.848ns | 850009.965ns | ~8649.64ns | 62.128%
⡇⠀⠀⢀⠀⠀⠀⡇⠀⡇⠀⠀⣠⠀⣿⠀⠀⠀⠀⡀⠀⠀⡆⠀⡆⢰⠀⠀⡆⠀⡄⠀⠀⠀⢠⢀⣼⠀⠀⡇⣠⣸⣤⡇⠀⡆⢸⠀⠀⠀⠀⢠⠀⢠⣿⠀⠀⢠⠀⠀⢸⢠⠀⡀
⣧⣶⣶⣾⣶⣷⣴⣿⣾⡇⣤⣶⣿⣸⣿⣶⣶⣶⣶⣧⣷⣼⣷⣷⣷⣿⣦⣴⣧⣄⣷⣠⣷⣶⣾⣸⣿⣶⣶⣷⣿⣿⣿⣷⣧⣷⣼⣦⣶⣾⣿⣾⣼⣿⣿⣶⣶⣼⣦⣼⣾⣿⣶⣷
val = reduce( shift, arr ) | 6489.921ns | 5094212.014ns | ~12040.269ns | 53.902%
这是原始性能测试,因此省略了endian pow-flip。
所示的shift
函数与for循环应用相同的移位或运算,而arr
仅array.array('B',[0,0,255,0])
,因为它具有dict
之后最快的迭代性能。>
我可能还应该注意到,效率是通过对平均时间的准确性来衡量的。
答案 11 :(得分:0)
在python 3中,您可以通过以下方式轻松地将字节字符串转换为整数列表(0..255)
>>> list(b'y\xcc\xa6\xbb')
[121, 204, 166, 187]