《Fluent Python》---一个关于memoryview例子的理解过程

系统 1525 0

近日,在阅读《Fluent Python》的第2.9.2节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询;

示例复述

添加了一些额外的代码,便于更好理解 memoryview

          
            >>> import array
>>> numbers = array.array('h', [-2, -1, 0, 1, 2])
>>> memv = memoryview(numbers)
>>> len(memv)
5
>>> memv[0]
-2
>>> memv_oct = memv.cast('B')
>>> memv_oct

            
              
>>> memv_oct.tolist()
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
>>> memv.tolist()
[-2, -1, 0, 1, 2]
>>> memv_oct[5] = 4
>>> numbers
array('h', [-2, -1, 1024, 1, 2])
>>> memv.tolist()
[-2, -1, 1024, 1, 2]
>>> memv_oct.tolist()
[254, 255, 255, 255, 0, 4, 1, 0, 2, 0]
            
          
        

我的理解和疑惑

  • nembers 是一个 signed short int 类型的数组;
  • memv 是使用上述数组创建的一个memoryview,即 内存视图 ,它使 memv 能够共享 nembers 数组的内存,但不需要复制里面的内容,这使得 memv 也能够访问和操作 numbers 数组的元素; memv[0] # -2 也就可以理解了。
  • memv.cast('B') memv 转换成一个 unsigned char int 的新 memoryview ,并返回给 memv_oct
  • memv_oct.tolist() 的元素比原始数组多了一倍:
    • signed short int在内存中是以2个字节存储,而 unsigned char int 在内存中则是1个字节存储。
    • memv.tolist() numbers 的内容还是一样的,所以 memoryview 只是换个角度看同一个事物,即所谓的 横看成岭侧成峰,远近高低各不同
    • 至此,我有一个不理解的地方:为什么 signed short int 类型的 -2 转换成 unsigned char int 类型时,变成 254 255
  • memv_oct[5] = 4 signed short int 类型的 0 的高字节赋值成 4 ;在二进制的层面下看,即 0000 0000 0000 0000 转换成了 0000 0000 0010 0000 ,十进制也就是1024;
  • 同时,我们也可以看到 memv.tolist() 也随着 numbers 改变了。更能说明 memoryview 只是对同一块数据的进行不同形式的表达;

解惑

正整数的情况可以理解,负整数的情况就理解不了,这说明正负整数在内存中的存储形式是不一样的。有了方向我们就直接搜一下吧。

  • signed short int 类型的 原码 最高位表示正负, 0 代表正数, 1 代表负数。
  • 它们内存中是以补码的形式存储的,其中正数的补码和原码相同;负数的补码,是其原码除符号位(即最高位)外,其余全部取反,再加1;
  • signed short int 类型的 -2 ,其原码为 0100 0000 0000 0001 ,除符号位取反,为 1011 1111 1111 1111 ,再加1,为 0111 1111 1111 1111 。当以 unsigned char int 类型读出来的时候,就成了 254 255 了; -1 亦是同理,即 255 255

总结

其实这都是《计算机组成原理》的基本知识,只是当我们习惯了使用一些高级编程语言的时候,对于这些底层的东西就不那么敏感了。


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论