• 《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

    总结

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

  • 相关阅读:
    多线程编程(二)--进程&amp;&amp;线程
    hdu2222 Keywords Search
    sqlserver 运行正則表達式,调用c# 函数、代码
    【Nutch2.2.1基础教程之2.2】集成Nutch/Hbase/Solr构建搜索引擎之二:内容分析
    ios学习之block初探
    PHP GD 生成图片验证码+session获取储存验证码
    ps 命令详解
    python --subprocess
    python --存储对象
    python --字符串格式化
  • 原文地址:https://www.cnblogs.com/luizyao/p/11415266.html
Copyright © 2020-2023  润新知