求 Python 中 int 转 bytes 最简/高效写法

2020-03-24 19:55:05 +08:00
 JCZ2MkKb5S8ZX9pq
3367 次点击
所在节点    Python
18 条回复
lxy42
2020-03-24 20:06:13 +08:00
In [20]: struct.pack('i', 0x123456)
Out[20]: b'V4\x12\x00'

这样吗?
JCZ2MkKb5S8ZX9pq
2020-03-24 20:19:53 +08:00
@lxy42
没用过这个,但看上去好像和 to_bytes 有点像。
那个需要指定长度和类型,但指定长度这个环节好像会有点小问题。
长度不够好像会报错。但如果长度过长,是不是效率反而低了?
另外可能是我没说清楚,是十进制转 bytes 。
JCZ2MkKb5S8ZX9pq
2020-03-24 20:22:31 +08:00
e.g.

for i in range(20):
j = str(i).encode('utf-8')
print(f'{type(i)} {i} -> {type(j)} {j}')

---

<class 'int'> 0 -> <class 'bytes'> b'0'
<class 'int'> 1 -> <class 'bytes'> b'1'
<class 'int'> 2 -> <class 'bytes'> b'2'
<class 'int'> 3 -> <class 'bytes'> b'3'
<class 'int'> 4 -> <class 'bytes'> b'4'
<class 'int'> 5 -> <class 'bytes'> b'5'
<class 'int'> 6 -> <class 'bytes'> b'6'
<class 'int'> 7 -> <class 'bytes'> b'7'
<class 'int'> 8 -> <class 'bytes'> b'8'
<class 'int'> 9 -> <class 'bytes'> b'9'
<class 'int'> 10 -> <class 'bytes'> b'10'
<class 'int'> 11 -> <class 'bytes'> b'11'
<class 'int'> 12 -> <class 'bytes'> b'12'
<class 'int'> 13 -> <class 'bytes'> b'13'
<class 'int'> 14 -> <class 'bytes'> b'14'
<class 'int'> 15 -> <class 'bytes'> b'15'
<class 'int'> 16 -> <class 'bytes'> b'16'
<class 'int'> 17 -> <class 'bytes'> b'17'
<class 'int'> 18 -> <class 'bytes'> b'18'
<class 'int'> 19 -> <class 'bytes'> b'19'
lxy42
2020-03-24 20:31:17 +08:00
struct 是 Python 的标准库, 可以将一些基本数据类型转化成字节数据, 例如 int 的 0x123456, 转化成 b'V4\x12\x00'.
wuwukai007
2020-03-24 20:33:09 +08:00
import pandas as pd
res = pd.Series(your_list).astype('bytes').tolist()
JCZ2MkKb5S8ZX9pq
2020-03-24 20:47:22 +08:00
@lxy42 好的,我去学习一下。
keepeye
2020-03-24 20:50:46 +08:00
bytearray([1])
ysc3839
2020-03-24 20:51:33 +08:00
最简单的方法是 int.to_bytes,但是某个版本的 Python 之前这个函数有性能问题。
所以追求最佳性能的话还是用 struct 吧。
imn1
2020-03-24 21:18:35 +08:00
楼上各位,“需求:1 -> b'1'”,并非 b'\x01',struct 还要每字节运算吧?
楼主的写法已经足够简单了,其中'utf8'还可以省去,str(i).encode()足够
wuwukai007
2020-03-24 21:20:43 +08:00
@imn1 我那个不是那种哦
JCZ2MkKb5S8ZX9pq
2020-03-24 21:38:42 +08:00
@imn1
的确你说的没错。用于校验的话,另几种算法结果是有问题的。

---

for i in range(10):
j = str(i).encode()
i = pd.Series([i]).astype('bytes').tolist()[0]
k = binascii.crc32(j)
print(f'{type(i)} {i} -> {type(j)} {j} | {k}')

<class 'int'> 0 -> <class 'bytes'> b'0' | 4108050209
<class 'int'> 1 -> <class 'bytes'> b'1' | 2212294583
<class 'int'> 2 -> <class 'bytes'> b'2' | 450215437
<class 'int'> 3 -> <class 'bytes'> b'3' | 1842515611
<class 'int'> 4 -> <class 'bytes'> b'4' | 4088798008
<class 'int'> 5 -> <class 'bytes'> b'5' | 2226203566
<class 'int'> 6 -> <class 'bytes'> b'6' | 498629140
<class 'int'> 7 -> <class 'bytes'> b'7' | 1790921346
<class 'int'> 8 -> <class 'bytes'> b'8' | 4194326291
<class 'int'> 9 -> <class 'bytes'> b'9' | 2366072709

---

@lxy42
j = struct.pack('i', i)

<class 'int'> 0 -> <class 'bytes'> b'\x00\x00\x00\x00' | 558161692
<class 'int'> 1 -> <class 'bytes'> b'\x01\x00\x00\x00' | 2583214201
<class 'int'> 2 -> <class 'bytes'> b'\x02\x00\x00\x00' | 2337085335
<class 'int'> 3 -> <class 'bytes'> b'\x03\x00\x00\x00' | 871461106
<class 'int'> 4 -> <class 'bytes'> b'\x04\x00\x00\x00' | 2921744459
<class 'int'> 5 -> <class 'bytes'> b'\x05\x00\x00\x00' | 379203374
<class 'int'> 6 -> <class 'bytes'> b'\x06\x00\x00\x00' | 70222016
<class 'int'> 7 -> <class 'bytes'> b'\x07\x00\x00\x00' | 3163809701
<class 'int'> 8 -> <class 'bytes'> b'\x08\x00\x00\x00' | 3840997363
<class 'int'> 9 -> <class 'bytes'> b'\t\x00\x00\x00' | 1548521622

---

@keepeye bytearray 出来的结果是 class 'bytearray',所以我改了下。
j = bytes([i])

<class 'int'> 0 -> <class 'bytes'> b'\x00' | 3523407757
<class 'int'> 1 -> <class 'bytes'> b'\x01' | 2768625435
<class 'int'> 2 -> <class 'bytes'> b'\x02' | 1007455905
<class 'int'> 3 -> <class 'bytes'> b'\x03' | 1259060791
<class 'int'> 4 -> <class 'bytes'> b'\x04' | 3580832660
<class 'int'> 5 -> <class 'bytes'> b'\x05' | 2724731650
<class 'int'> 6 -> <class 'bytes'> b'\x06' | 996231864
<class 'int'> 7 -> <class 'bytes'> b'\x07' | 1281784366
<class 'int'> 8 -> <class 'bytes'> b'\x08' | 3705235391
<class 'int'> 9 -> <class 'bytes'> b'\t' | 2883475241

---

@wuwukai007 pandas 的方法,结果是正确的,就是圈子兜得也略有点大。
j = pd.Series([i]).astype('bytes').tolist()[0]

<class 'int'> 0 -> <class 'bytes'> b'0' | 4108050209
<class 'int'> 1 -> <class 'bytes'> b'1' | 2212294583
<class 'int'> 2 -> <class 'bytes'> b'2' | 450215437
<class 'int'> 3 -> <class 'bytes'> b'3' | 1842515611
<class 'int'> 4 -> <class 'bytes'> b'4' | 4088798008
<class 'int'> 5 -> <class 'bytes'> b'5' | 2226203566
<class 'int'> 6 -> <class 'bytes'> b'6' | 498629140
<class 'int'> 7 -> <class 'bytes'> b'7' | 1790921346
<class 'int'> 8 -> <class 'bytes'> b'8' | 4194326291
<class 'int'> 9 -> <class 'bytes'> b'9' | 2366072709

---

@ysc3839 to_bytes 我一开始试了,有个长度参数的问题,没想好怎么处理。另外它输出的结果好像也是 b'\x00\x01'这类的。
ClericPy
2020-03-24 21:44:58 +08:00
我还真去 google 了一下... 关键词都没多加, 这问题问的还挺多, 最不动脑子的还就是楼主给的...

https://www.google.com/search?q=Python%20int%20to%20bytes
JCZ2MkKb5S8ZX9pq
2020-03-24 21:48:26 +08:00
@ClericPy 我也 google 了,就是觉得试了集中都不大理想,所以上来问问,蹲蹲看高手。
ysc3839
2020-03-24 21:49:56 +08:00
@imn1 @JCZ2MkKb5S8ZX9pq
多谢提醒,是我理解错了。楼主这个需求用 str(i).encode() 应该是最简单高效的。
JCZ2MkKb5S8ZX9pq
2020-03-24 21:50:57 +08:00
@ClericPy 主要就是觉得从 string 绕一下再 encode 可能有点绕。
另外感觉这需求还挺基础的,想问问看有啥内置的我不知道的方法。
wuwukai007
2020-03-24 21:52:18 +08:00
@JCZ2MkKb5S8ZX9pq 我以为你要做的批量数据,只是一个的话,丑陋点正常哈
JCZ2MkKb5S8ZX9pq
2020-03-24 21:53:46 +08:00
@wuwukai007 嗯,pandas 我确实也在学,不过都是结合需求,现用现搜。
milkpuff
2020-03-24 22:21:07 +08:00
d = {i:str(i).encode() for i in range(10)}
d[1]

从 dict 索引比直接转换快

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/655812

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX