本系列文章是一系列学习笔记,希望较为深入地分析Python3中的原理、性能,文章中绝大部分观点都是原作作者的观点(如下),本人对书中示例加以实践和总结,并结合相应的Python的C语言源码(3.6.1),分享出来。原著:
- 《High Performance Python》by O'Relly Media,作者Micha Gorelick,Ian Ozsvald
- 《Fluent Python》by O'Relly Media,作者Luciano Ramalho
Python程序员有时候会过度使用List,因为List太灵活太好用了!我就是这样。
针对各种需求,List并不是一个好的选择:
- 需要存储1百万个数字时,array是更好的选择,array不会抽象float object,而是用bytes来表示数字,就像C语言那样。
- 我们经常会做一些包含检查(containment checks),比如,一个值在不在一个集合里,这种情况下,请用集合(sets),集合针对成员检查做了特别的优化。
a = 2
if a in [1,2,3]:
pass
else:
pass
Arrays
- 如果一个列表仅仅包数字,那么,array.array比List更加高效。array支持所有可变序列的方法,还有一些附加方法用来导入导出数据,比如,.frombytes, .tofile。
- Python的array的紧凑程度类似于C语言的数组。
- array.tofile和array.fromfile也很方便高效
>>> from array import array
>>> from random import random
>>> nums = array('d', (random() for i in range(10**7)))
>>> nums[-1]
0.627233014646329
>>>
>>> fp = open('tmp', 'wb')
>>> nums.tofile(fp)
>>> fp.close()
>>>
>>> nums_import = array('d')
>>> fp = open('tmp', 'rb')
>>> nums_import.fromfile(fp, 10**7)
>>> nums_import[-1]
0.627233014646329
>>> nums_import == nums
True
>>> fp.close()
>>>
Memory Views
书中作者说,如果你经常用arrays,但是不知道Memory Views,那么我OUT了。我还真不知道。。。
Memory Views是内置类型,是一个共享内存的序列,lets you handle slices of arrays without copying bytes。这个也是NumPy的基础。在C语言中,有很多类型,unsigned char就是1bytes,signed char就是2bytes,书中的列子是创建一个5个signed char的序列,然后转换成unsigned char,10个~,修改一个bytes,然后转回signed char,这中间没有copy操作,只是在处理内存,其实,这对我们写出高效率的算法还是很有帮助的。
>>> numbers = array('h', [-2,-1,0,1,2])
>>> memv = memoryview(numbers)
>>> memv
<memory at 0x1019f0648>
>>> len(memv)
5
>>> memv[1]
-1
>>> memv_oct = memv.cast('B')
>>> memv_oct.tolist()
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
>>>
>>> len(memv_oct)
10
>>> memv_oct[0]
254
>>> memv_oct[5] = 4
>>> numbers
array('h', [-2, -1, 1024, 1, 2])
>>>
NumPy和SciPy
毋庸置疑,这两个库让Python在科学计算领域成为主流,这两个库的使用不在这里介绍。C和Fortran的性能,Python的API。