记录博客 ZH-BLOG

Python 其它存储类型

时间:2018-08-01 15:45:46分类:python

python 列表很灵活,但不是所有需求下都是最好的选择。

如果要存储大量数值的话,数组的效率更高。

如果要频繁对序列做先进先出的操作,deque(双端队列)的速度应该会更快。

如果需要频繁判断是否包含操作,set(集合)会更合适。

1. 数组

>>> arr=array('d',[1,2,3])
>>> arr
array('d', [1.0, 2.0, 3.0])
>>> arr.count(1)  # 1在数组中出现的次数
1
>>> 2 in arr  # 判断2是否在数组中
True
>>> arr.extend([1,2,3])   # 在数组末尾加上[1,2,3]
>>> arr
array('d', [1.0, 2.0, 3.0, 1.0, 2.0, 3.0])
>>> arr=array('d',[1,4,6,2,4,7,9,4,6])
>>> arr
array('d', [1.0, 4.0, 6.0, 2.0, 4.0, 7.0, 9.0, 4.0, 6.0])
>>> a=array(arr.typecode,sorted(arr)) # 数组类型不支持诸如 list.sort() 这种就地排序方法。 要给数组排序的话, 得用 sorted 函数新建一个数组
>>> a
array('d', [1.0, 2.0, 4.0, 4.0, 4.0, 6.0, 6.0, 7.0, 9.0])

from array import array
from random import random
import os

doubles=array('d',(random() for i in range(10**7))) # 利用一个可迭代对象来建立一个双精度浮点数组(类型码是 'd')
print(doubles[-1])
fp=open(os.path.join('E:\\','path','array.bin'),'wb')
doubles.tofile(fp)  # 把数组存入一个二进制文件里
fp.close()

doubles2=array('d') # 新建一个双精度浮点空数组
fp=open(os.path.join('E:\\','path','array.bin'),'rb')
doubles2.fromfile(fp,10**7) # 从文件读取 1000 万个浮点数
fp.close()
print(doubles2[-1])

print(doubles==doubles2)    # True

2. 内存视图

import array

numbers=array.array('h',[-2,-1,0,1,2])  # h: int 2 bytes
memv=memoryview(numbers)
print(len(memv))
print(memv[-1]) # 基本操作跟数组里没有区别
memv_oct=memv.cast('B') # B: unsigned char 1 bytes
print(memv_oct.tolist())    # 以列表形式显示
memv_oct[5]=4   # 把位于位置 5 的字节赋值成 4
print(numbers)  # numbers此时被修改

# 分析
# -2 (h: int 2 bytes)
# 10000000 00000010 (-2原码)
# 取反+1(符号位不变):
# 11111111 11111101 +1 = 11111111 11111110
# unsigned char 1 bytes:
# 255 254
# -1 (h: int 2 bytes)
# 10000000 00000001 (-1原码)
# 取反+1(符号位不变):
# 11111111 11111110 +1 = 11111111 11111111
# unsigned char 1 bytes:
# 255 255
# 0 (h: int 2 bytes)
# 00000000 00000000
# 正数不变
# unsigned char 1 bytes:
# 0 0
# 1 (h: int 2 bytes)
# 00000000 00000001
# 正数不变
# unsigned char 1 bytes:
# 0 1
# 2 (h: int 2 bytes)
# 00000000 00000010
# 正数不变
# unsigned char 1 bytes:
# 0 2
# 结果:
# 254,255,255,255,0,0,1,0,2,0
# memv_oct[5]=4   # 把位于位置 5 的字节赋值成 4
# 254,255,255,255,4,0,1,0,2,0
# 4,0
# 00000100 00000000
# 2**10=1024
# numbers:
# -2,-1,1024,1,2


# 资料:
# 负数以原码的补码形式表达。

# 1、原码:
# 一个正数,按照绝对值大小转换成的二进制数;一个负数按照绝对值大小转换成的二进制数,然后最高位补1,称为原码。
# 比如 00000000 00000000 00000000 00000101 是 5 的原码。
#     10000000 00000000 00000000 00000101 是 -5 的原码。

# 2、补码
# 正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.
# 比如 -5 :
#       10000000 00000000 00000000 00000101 取反是:11111111 11111111 11111111 11111010。
# 然后在最后一位加1,那么,补码为:
# 11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
#

# 备注:1、从补码求原码的方法跟原码求补码是一样的 ,也可以通过完全逆运算来做,先减一,再取反。
#       2、补码却规定0没有正负之分

3. 双向队列

>>> from collections import deque
>>> dq = deque(range(10), maxlen=10)
>>> dq
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.rotate(3)
>>> dq
deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
>>> dq.rotate(-4)
>>> dq
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
>>> dq.appendleft(-1)
>>> dq
deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.extend([11, 22, 33])
>>> dq
deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10)
>>> dq.extendleft([10, 20, 30, 40])
>>> dq
deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8], maxlen=10)