流畅的python——4月23日读书笔记

2.9 2.9 2.9 当列表不是首选时

上篇blog最后提到了,虽然目前list十分好用又灵活,但是有一些时候,针对不同的需求,不一定要用到列表。

我们就来了解一下上次提到的数组:
它支持所有和可变序列有关的操作,包括(.pop .insert .extend)等。

>>> from array import array
>>> from random import random
>>> floats = array('d', (random() for i in range(10**7)))
>>> floats[-1]
0.004257761334989896
>>> fp = open('floats.bin', 'wb')
>>> floats.tofile(fp)
>>> fp.close()
>>> floats2 = array('d')
>>> fp = open('floats.bin', 'rb')
>>> floats2.fromfile(fp, 10**7)
>>> fp.close()
>>> floats2[-1]
0.004257761334989896
>>> floats2 == floats
True

把一千万个浮点数存在二进制文件中,每个占用8个字节,总共也就是80,000,000个字节。如果是文本文件,则还需用内置的float方法将文字转为浮点数。显然第一种的速度会快的多。

之前在写一个操作redis库的操作时,需要把取得的value值转换一下类型。用到了一个pickle模块。python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化。它有个pickle.dump()的方法,也可以用来处理上述的浮点数问题。


简单总结一些常用的列表与数组的属性和方法:

methodlistarraydesc
s.__ add__(s2)s+s2 拼接
s.append()在尾部追加元素
s.copy()对列表浅复制
s.count(e)s中e出现的次数
s.index(e)找到e在s中第一次出现的位置
s.__ iter__()返回迭代器
s.insert(p,e)在为于p的位置前插入e
s.pop([p])删除位于p的值并返回
s.tobytes()把元素的机器值用bytes对象的形式返回

我们可以利用memoryview来精确修改一个数组的某一个字节。
实例如下:

>>> numbers = array('h', [-2,-1,0,1,2])
>>> memv = memoryview(numbers)
>>> len(memv)
5
>>> memv[0]
-2
>>> memv_oct = memv.cast('B')
# 创建一个memv_oct,将memv中的内容转换为‘B’类型,也就是无符号字符
>>> memv_oct.tolist()
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
>>> memv_oct[5] = 4
>>> numbers
array('h', [-2, -1, 1024, 1, 2])

其中memv.cast()方法会将同一块内存中的内容打包成一个新的memoryview对象给我们。

然后我们将memv_oct[5]的值改为4,也就是2的2次方。由于改动的是原先第3个数字的高位。所以是所占的16位中的第10位为1,也就是2的10次方。因此再次输出numbers时。0变成了1024。

2.9.3 2.9.3 2.9.3 Numpy和Scipy
python目前成为优秀的机器学习的主流语言,很大一程度上在于Numpy和Scipy提供的高阶数组和矩阵操作。NumPy是Python中的一个运算速度非常快的一个数学库。Scipy是基于Numpy的另一个库,它提供了很多的与科学计算有关的算法。这两者的功能十分强大,鉴于目前的程度,我只做简单的理解和学习。(小声bb:以前了解数据分析的时候也接触过,函数方法很多,可以应用在各种数学场景中,太厉害了。)

接下来一个简单的示例:

>>> import numpy
>>> a = numpy.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> type(a)
<class 'numpy.ndarray'>
>>> a.shape
(10,)
>>> a.shape = 2,5
>>> a
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> a[1]
array([5, 6, 7, 8, 9])
>>> a.transpose()
array([[0, 5],
       [1, 6],
       [2, 7],
       [3, 8],
       [4, 9]])

使用NumPy提供的这些数组和方法,我们就可以以闪电般的速度执行各种有用的操作,如矢量和矩阵、线性代数等数学运算!

第三章 字典与集合

dict类型是python语言的基石。由{key-value}的结构组成。
collections.abc模块中有Mapping和MutableMapping这两个抽象基类。它们的作用是为是为dict和其它类似的类型定义形式接口。

但是一般非抽象的映射类型不会直接继承这些抽象基类,它们会直接对dict或是collections.UesrDict进行扩展。
让我们来检验一下:

>>> from collections.abc import Mapping
>>> my_dict = {}
>>> isinstance(my_dict, Mapping)
True

字典可以由以下多种方式创建:

>>> a = dict(one=1, two=2,three=3)
>>> b = {'one': 1, "two": 2, "three":3}
>>> c = dict(zip(['one', 'two', 'three'], [1,2,3]))
>>> d = dict([('one', 1), ('three',3), ('two',2)])
>>> a ==b ==c==d
True

除了这些,还可以使用字典推导的方式:
3.2 3.2 3.2 字典推导
字典推导可以从任何以键值对作为元素的可迭代对象中构建出字典。
示例如下:

>>> zidian = [(1,'zhang'),(2,'fei'),(3,'qi'),(4,'bai')]
>>> test = {age: name for name,age in zidian}
>>> test
{'zhang': 1, 'fei': 2, 'qi': 3, 'bai': 4}

该实例就是将一个装满元组的列表变成了一个字典格式。


collections中有两个数据类型为dict的变种:
OrderedDict 可以理解为有序的dict,底层源码是通过双向链表来实现,每一个元素为一个map存储key-value。
defaultdict是当修改未初始化的key-value时,会用默认值替换。

下表是对这三种dict的常用方法做了一个概括:

methoddictdefaultdictorderedDictdesc
d.__ contains__(k)检查k是否在d中
d.copy()浅复制
d.clear()移除所有元素
d.get(k,[default])返回键k对应的值,如果字典里没有键k,则返回none或者default
d.items()返回d中所有的键值对
d.keys()获取所有的键
d.__ len__()可以用len(d)的形式得到字典里键值对的数量
d.popitem()随机返回一个键值对并且从字典中移除
d.values()返回字典里的所有值
d.update(m,[**kargs])m为映射或者键值对迭代器,用来更新d中的元素
d.setdefault(k,[default])若字典中有键k,则返回k对应的value,否则返回default值

在代码中,我尝尝会这样写:

>>> b = {'one': 1, "two": 2, "three":3}
>>> if key not in b:
...     b[key] = []
>>> b[key].append(value)
>>> b
{'one': 1, 'two': 2, 'three': 3, 1: ['ao']}

实际上类似于:

>>> b.setdefault('new', []).append(value)
>>> b
{'one': 1, 'two': 2, 'three': 3, 1: ['ao'], 'new': ['ao']}

但是前者中两个b[key]会用到两次键查询。而后者只用到一次就可以了。而且代码量明显少多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值