V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
JCZ2MkKb5S8ZX9pq
V2EX  ›  Python

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

  •  
  •   JCZ2MkKb5S8ZX9pq · 2020-03-24 19:55:05 +08:00 · 3448 次点击
    这是一个创建于 1703 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 需求:1 -> b'1',结果用来算校验码。
    • 注意:不是十进制转二进制
    • 类似:str(i).encode('utf-8')
    • 语言:py3
    18 条回复    2020-03-24 22:21:07 +08:00
    lxy42
        1
    lxy42  
       2020-03-24 20:06:13 +08:00
    In [20]: struct.pack('i', 0x123456)
    Out[20]: b'V4\x12\x00'

    这样吗?
    JCZ2MkKb5S8ZX9pq
        2
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-24 20:19:53 +08:00
    @lxy42
    没用过这个,但看上去好像和 to_bytes 有点像。
    那个需要指定长度和类型,但指定长度这个环节好像会有点小问题。
    长度不够好像会报错。但如果长度过长,是不是效率反而低了?
    另外可能是我没说清楚,是十进制转 bytes 。
    JCZ2MkKb5S8ZX9pq
        3
    JCZ2MkKb5S8ZX9pq  
    OP
       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
        4
    lxy42  
       2020-03-24 20:31:17 +08:00
    struct 是 Python 的标准库, 可以将一些基本数据类型转化成字节数据, 例如 int 的 0x123456, 转化成 b'V4\x12\x00'.
    wuwukai007
        5
    wuwukai007  
       2020-03-24 20:33:09 +08:00
    import pandas as pd
    res = pd.Series(your_list).astype('bytes').tolist()
    JCZ2MkKb5S8ZX9pq
        6
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-24 20:47:22 +08:00
    @lxy42 好的,我去学习一下。
    keepeye
        7
    keepeye  
       2020-03-24 20:50:46 +08:00
    bytearray([1])
    ysc3839
        8
    ysc3839  
       2020-03-24 20:51:33 +08:00 via Android
    最简单的方法是 int.to_bytes,但是某个版本的 Python 之前这个函数有性能问题。
    所以追求最佳性能的话还是用 struct 吧。
    imn1
        9
    imn1  
       2020-03-24 21:18:35 +08:00   ❤️ 2
    楼上各位,“需求:1 -> b'1'”,并非 b'\x01',struct 还要每字节运算吧?
    楼主的写法已经足够简单了,其中'utf8'还可以省去,str(i).encode()足够
    wuwukai007
        10
    wuwukai007  
       2020-03-24 21:20:43 +08:00
    @imn1 我那个不是那种哦
    JCZ2MkKb5S8ZX9pq
        11
    JCZ2MkKb5S8ZX9pq  
    OP
       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
        12
    ClericPy  
       2020-03-24 21:44:58 +08:00
    我还真去 google 了一下... 关键词都没多加, 这问题问的还挺多, 最不动脑子的还就是楼主给的...

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

    从 dict 索引比直接转换快
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1063 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 19:16 · PVG 03:16 · LAX 11:16 · JFK 14:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.