ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

从memory对象看Numpy中的ndarray对象

2021-01-05 17:36:01  阅读:205  来源: 互联网

标签:字节 buffer mev memory print array x00 Numpy ndarray


memoryview对象

  • 内存视图:简化一句话就是在不copy数据的情况下,与其他对象能够共享同一个内存地址,达到操作数据的目的,在处理大量数据的时候能够极大降低内存的开销。这个类的概念灵感来自于Numpy的数组。Numpy作者回答
    • memoryview对象属性及方法:仅仅涉及部分方法属性
import array
mev= memoryview(array.array('i',[1,2,3])) # memoryview(obj) obj必须是实现了缓冲协议的对象 例如bytes(字节)、bytearray、array.array
print(mev) #打印memor对象  <memory at 0x114293ac8>
print(mev.tolist()) # [1, 2, 3] obj的列表形式
print(mev.tobytes()) # b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
# 接上:返回字节串形式,因为在array中字节类型码是i 代表signed int(有符号整数) 2个字节  打印出 每个元素字节其实是4 bytes,
#接上:16进制表示那就是1 代表是 b'\x01\x00\x00\x00
# 接上:返回的形式中存在小端 1 16进制 4字节表示其实是:0x00 0x00 0x00 0x01
print(mev.hex()) # 两位16进制  因为是4字节  表示buffer中的数据 1(01 00 00 00) 2 (02 00 00 00)3(03 00 00 00)

c= array.array('i',[1,2000,3])
print(c.itemsize) #打印出 每个元素字节可以看出其实是4 bytes
print(c.tobytes()) # b'\x01\x00\x00\x00\xd0\x07\x00\x00\x03\x00\x00\x00' 同memoryview

  • memory对数据的修改:
      import array
      c = array.array('i',[1,2,3]) 
      mev= memoryview(c) # memoryview(obj) obj必须是实现了缓冲协议的对象 例如bytes(字节)、bytearray、array.array
      mev[1] =4  #mev支持index slicing
      print(mev[1]) # 整数索引 返回对应位置元素值 1
      print('第一次修改:',c)   # array('i', [1, 1, 3]) 原生数组c索引位置为1的已经被修改

      k = mev[0:1] #memoryview支持切片 返回对象仍然是 memoryview
      print(k) # <memory at 0x1133d0a08>
      
import array
c = array.array('i',[1,2,3])
mev= memoryview(c) # memoryview(obj) obj必须是实现了缓冲协议的对象 例如bytes(字节)、bytearray、array.array

print(c.itemsize) # 4
print(mev.itemsize) # mev中内容每个元素大小均是4个字节


mev_cast= mev.cast('B') # cast 函数 返回一个memoryview 并将原来的视图里面的内容进行类型转换 转换成无符号 此时每个元素只有1个字节
print(mev_cast.tolist()) # 未修改 索引3之前 [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]
mev_cast[3]=4  # 
print(mev_cast.itemsize)  # 1  mev_cast中每个元素大小均为1bytes

print('mev_cast :',mev_cast.hex()) # 输出结果  010000040200000003000000
print('mev:',mev.hex())  # 输出结果  010000040200000003000000

print('kaishi1',c) # 输出结果 kaishi1 array('i', [67108865, 2, 3])
print(mev_cast.tolist())  # [1, 0, 0, 4, 2, 0, 0, 0, 3, 0, 0, 0] # 之前是4个字节为1个单位 现在被拆分成1个字节为单位,总共12个元素 = 3*4,上述mev_cast[3]=4 修改的其实是该列表
对于其他类型属性需要参照各自存储方式:有符号数存在符号位,并且在计算机内存中储存的是补码。

ndarry构造方法

  • numpy中常见构造方法各种博客都有介绍,今天写一下ndarry这个在官方中成为low-level构造ndarry对象的方法,在探究的过程还发现了ndarry与memoryview对象其中不少的关系,写下本文放方便以后记录学习。
    • numpy.ndarry(shape,buffer,offset,dtype,strides,order):各参数解释如下:
      1.shape: 由整数组成的元组,表示创建的ndarry对象的形状,其实就是数组在各个轴上或者维度上的元素的个数;

      2.buffer:暴露缓冲接口的对象 用数据填充这一array数组。当我们需要buffer缓冲数据由其他来源来创建,并且这一来源还不是可以被重塑(reshape)以及view的ndarry ;这一观点来自于用指定数据创建ndarry对象
      3.offset:在buffer数据中偏移量,其实也是指代了buffer中数据的开始的位置
      4.dtype:数组中数据类型
      5.strudes:跨度
      6.order:‘C’--代表行优先,‘F’代表列优先

问题背景

  • buffer在创建ndarray中的作用
    • buffer为None的时候:输出的数组是随机 random
import  numpy as np
k = np.ndarray(shape=(4,2), dtype=int, order='c')
print(k)
out: 
[[-8070450532247928832 -8070450532247928832]
 [ 8027794400713703428  7811887657498193774]
 [ 7815259820786999141  8245937481777164148]
 [ 7310584009609916025     1125904217407488]]
  • buffer不为None的时候:
import numpy as np
k = np.array([1,2,3,4])
num = np.ndarray(shape=(2,1),buffer=k,dtype=int,offset=1)  
# num = np.ndarray(shape=(2,1),buffer=k.data,dtype=int,offset=1)  上述中传入buffer的其实是作为ndarray对象k中的data (Python buffer object pointing to the start of the array’s data.)
print(k.data.__class__) # <class 'memoryview'> 代表一个memory对象

import numpy as np
k = np.array([1,2,3,4])
# 现在来分别测试 buffer 以及offset
#buffer
num_buffer = np.ndarray(shape=(2,1),buffer=k,dtype=int)

print(num_buffer.data.hex()) # 01000000000000000200000000000000
print(num_buffer.tolist()) # [[1], [2]]
print(num_buffer.tobytes()) # b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00' 小端模式返回字节数据
print(num_buffer.itemsize) # 每个元素对应大小是8个字节 [1]对应字节是 :b'\x01\x00\x00\x00\x00\x00\x00\x00 内存存储形式 同上

# buffer and offset

num = np.ndarray(shape=(2,1),buffer=k,dtype=int,offset=1)

print(num.data.hex()) # 00000000000000020000000000000003
print(num.tolist()) # [[144115188075855872], [216172782113783808]]
print(num.tobytes()) # b'\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03'小端模式返回字节数据
print(num.itemsize) # 每个元素对应大小是8个字节 [144115188075855872]对应字节是 :b'\x00\x00\x00\x00\x00\x00\x00\x02 内存存储形式 同上


import struct
value = struct.unpack('<q',b'\x00\x00\x00\x00\x00\x00\x00\x02') #将字节按照指定格式转换为数值,因为需要转化成8个字节大小的数据 所以数据类型选用了'q'
print(value) # value 144115188075855872

# 在num中每个数据类型是int64位,8个字节,以下分别代表offset不同偏移位置
#-2b'\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00'
#-1b'\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00'
#  b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00
#0 b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00'
#1 b'\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03'
#2 b'\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00'
#3 b'\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00'
#4 b'\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00'
#5 b'\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00'
#6 b'\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00'
#7 b'\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00'
#8 b'\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'
#9 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04'
#10 b'\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00'
#11 b'\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00'
12 b'\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00'
13 b'\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00'
'''
#当偏移量是itemsize =8 的整数倍的时候就相当于对对buffer数据源进行切片操作
nu1 = np.ndarray(shape=(2,1),buffer=k,dtype=int,offset=8)
print(nu1) # [[2] [3]]
value =  k[1:3].reshape(2,1) #偏移8个字节 相当于1个元素,所以起始所以为1,总共包含2个元素 end-1=2  即为3
print(value) # [[2] [3]]

总结

虽然创建ndarry对象基本不会使用numpy.ndarray这个创造对象方法,但是对于背后的了解其实发现涉及到缓冲区、字节数据转换、计算机存储形式、内存视图(view)概念有很多帮助。
在查看numpy概念中了解到背后使用了C语言中指针 结构体,所以接下来将会进一步深化对概念的理解。

标签:字节,buffer,mev,memory,print,array,x00,Numpy,ndarray
来源: https://www.cnblogs.com/ivan09/p/14234821.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有