本来第一次看《流畅的python》觉得这部分没用,就跳过去,后面又出现,回头看还是一知半解,查了诸多资料,好像有一点明白了,立下帖子。
1、memoryview
memoryview()
函数返回给定参数的内存查看对象(memory view)。
所谓内存查看对象,是指对支持缓冲区协议的数据进行包装,在不需要复制对象基础上允许Python代码访问。
可以简单理解为就是对内存地址的直接访问。
memoryview可以对对象进行索引或者切片,不过切片的返回结果为一个子memoryview对象:
import array
# 创建一个signed short 类型数组,占2bytes
nums = array.array('h', list(range(-2, 3)))
mem = memoryview(nums)
print(len(mem)) # 5
print(mem[0]) # -2
print(mem[1:4]) #
mem相当于nums在内存中的表示形式,但是属于不同的对象:
>>>mem is nums
False
>>>mem == nums
True
同样,memoryview对象有tolist方法可以转换为列表:
>>>mem.tolist()
[-2, -1, 0, 1, 2]
2、memoryview.cast
memoryview.cast
会把同一块内存里的内容打包成一个全新的memoryview对象。
>>>mem_oct = mem.cast('B')
>>>mem.nbytes == mem_oct.nbytes
True
>>>mem.itemsize == mem_oct.itemsize
False
在转换以后,所占字节数保持不变,但是单个元素的所占字节由原来的2个变成1个(‘h’ --> ‘B’)。
Type code
C Type
Python Type
Minimum size in bytes
‘c’
char
character
1
‘b’
signed char
int
1
‘B’
unsigned char
int
1
‘u’
Py_UNICODE
Unicode character
2 (see note)
‘h’
signed short
int
2
‘H’
unsigned short
int
2
‘i’
signed int
int
2
‘I’
unsigned int
long
2
‘l’
signed long
int
4
‘L’
unsigned long
long
4
‘f’
float
float
4
‘d’
double
float
8
将mem_oct转换为list,你会发现mem_oct居然包含10个元素:
>>>mem_oct.tolist()
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
所包含的元素也很奇怪,这个就涉及到存储的一些知识,为了将将符号位和数值域统一处理,同时加法和减法也可以统一处理,计算机系统中数值一律用补码来表示和存储。
以-2为例,初始设置其数据类型为占用两个字节的’long’,其原码是1000 0000 0000 0010,而在计算机存储的是1111 1111 1111 1110,其低八位为254,高8位为255,所以知道mem_oct前两个元素从哪里来了吧。
对于2来说,原码为0000 0000 0000 0010,补码为其本身(正数的补码与原码一致),所以转换后为2,0。
欢迎关注我的微信公众号