【问题标题】:How can I perform C-Style Typecasting in Python?如何在 Python 中执行 C 样式类型转换?
【发布时间】:2017-02-02 00:55:11
【问题描述】:

假设我有以下np.uint8 数组:

In [9]: a = np.array([0x34, 0xF3, 0x87, 0x42]).astype(np.uint8)
In [10]: a
Out[10]: array([0x34, 0xf3, 0x87, 0x42], dtype=uint8)

现在,当我转换为 np.uint16 时,我得到以下信息:

In [11]: b = a.astype(np.uint16)
In [12]: b
Out[12]: array([0x34, 0xf3, 0x87, 0x42], dtype=uint16)

这是预期会发生的,但我想要别的。 例如,在 C 语言中,当您拥有类型为 uint8 (unsigned char) 的相同数组并且您想要访问它时,就好像它是包含 uint16 (unsigned short) 元素的数组一样:

unsigned char a[] = {0x34, 0xF3, 0x87, 0x42};
unsigned short* b = (unsigned short*)a;

这会给我,正如 C 所期望的那样:

0x34 0xF3 0x87 0x42  // for a
0xF334    0x4287     // for b, little or big endian, for me doesn't matter

现在我的问题是,我怎样才能在 Python 中做这种事情? (是否甚至可以在不创建新数组的情况下从一种类型转换为另一种类型?)

我可以通过位移和添加两个字节来创建一个新数组,如下所示:

#! /usr/bin/python3

import numpy as np

np.set_printoptions(formatter={'int':hex})

# I assume, a has the len 2*n  and b has the len n (for conversion from 2*n Bytes in n 2Bytes)
a = np.array([0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93]).astype(np.uint8)
b = np.array([(a[2*i]<<8)+a[2*i+1] for i in range(0, len(a) // 2)]).astype(np.uint16)

print("a: {}".format(a)) # a: [0x31 0x41 0x59 0x26 0x53 0x58 0x97 0x93]
print("b: {}".format(b)) # b: [0x3141 0x5926 0x5358 0x9793]

我需要这个用于非常大的数组(或多或少),所以我想问这是否可以在 Python 中更有效地完成。

【问题讨论】:

    标签: python python-3.x numpy type-conversion


    【解决方案1】:
    b = a.view(np.uint16)
    

    这是一个危险且容易出错的操作。请牢记在 C++ 中应牢记的所有相同注意事项,例如字节序。您还需要担心其他注意事项,例如不连续的数组内存布局。至少严格的别名是别人的问题;该实现可能违反了 C 严格的别名规则,但希望他们设置编译器标志或其他东西来获得定义的行为。 (uint8unsigned char,因此不适用严格的别名,但 ndarray.view 也允许 uint64->float64 重新解释之类的内容。)

    【讨论】:

    • 所以基本上你不会推荐我做例如b = a.view(np.uint16)?对于我的问题,我只会将 uintX 转换为 uintY。小端转换也不是问题。因为我有(具体来说)一个 S-Box,所以我需要它。我也可以在 Python 中设置任何标志来获得定义的行为吗? (例如,让 numpy 获得大端或小端等)
    • @PiMathCLanguage:你可以specify the endianness of a dtype。例如,np.array(..., dtype='&lt;i2') 将使用 little-endian 2 字节整数的 dtype,而 dtype='&gt;i2' 将使用 big-endian。
    【解决方案2】:

    我实际上不建议这样做 (@user2357112 already explained why),但您也可以手动更改(设置)dtype 属性:

    >>> import numpy as np
    >>> a = np.array([0x34, 0xF3, 0x87, 0x42]).astype(np.uint8)
    >>> a.dtype = np.uint16
    >>> a
    array([62260, 17031], dtype=uint16)
    

    【讨论】:

      猜你喜欢
      • 2011-10-30
      • 1970-01-01
      • 2013-10-15
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多