zoukankan      html  css  js  c++  java
  • 《Fluent Python》 -- 一个关于memoryview例子的理解过程

    近日,在阅读《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
    <memory at 0x10869d7c8>
    >>> 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()的元素比原始数组多了一倍:
    • memv_oct[5] = 4signed 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

    总结

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

  • 相关阅读:
    flask的简单使用
    Android Studio 使用Lambda表达式
    安卓SDK更新 国内镜像站点记录
    REACT-NATIVE入门(环境搭建及HELLOWORLD)
    深入理解Android 读感(一)
    JNI初入手
    (转)c++ 中的using namespace std是什么意思,什么时候用
    (转)const char to LPCTSTR不能转化问题
    Git常用操作之add操作
    Git日志操作
  • 原文地址:https://www.cnblogs.com/luizyao/p/11415266.html
Copyright © 2011-2022 走看看