一.为啥需要numpy
python虽然说注重优雅简洁,但它终究是需要考虑效率的.别说运行速度不是瓶颈,在科学计算中运行速度就是瓶颈.
python的列表,跟java一样,其实只是一维列表.一维列表相当于一种类型,这样对于元素的访问效率是很低的.
python中一切皆引用,每一个int对象都要用指针指一下再用int存储一下,浪费空间也浪费时间.当读取某个元素的时候需要先读取引用,再根据引用指向的内存地址来读取int值.
numpy相当于完全采用了C语言那套数组机制.
二.numpy原则
- 一切皆一维,多维只是马甲
多维数组的内部实现就是一维. - 定长,一切皆矩形,一切皆长方体.
比如定义了一个数组a[3],则
len(a[0])=len(a[1])=len(a[2]),各个元素不能变长
正是因为定长这个原则,才有可能能实现"一切皆一维"这个原则. - 数组中元素类型相同,长度相同
numpy中的数组都是一维数组,并且这个一维数组中每个元素的长度相同,各个元素属于同一种类型.
numpy中的元素相当于结构体,一个结构体所占字节数是固定的,numpy是允许用户自定义结构体类型的. - 数组就是一块空间
想对它作何解释就作何解释,想给它穿上什么马甲就给它穿上什么马甲.对于一个包含24个元素的一维数组,可以把它理解为4*6或者2*12或者3*8的二维数组,也可以把它理解为2*2*6或者3*2*4的三维数组.
三.numpy概念
- ndarray.ndim
数组轴的个数,在python的世界中,轴的个数被称作秩 - ndarray.shape
数组的维度。这是一个指示数组在每个维度上大小的整数元组。例如一个n排m列的矩阵,它的shape属性将是(2,3),这个元组的长度显然是秩,即维度或者ndim属性 - ndarray.size
数组元素的总个数,等于shape属性中元组元素的乘积。 - ndarray.dtype
一个用来描述数组中元素类型的对象,可以通过创造或指定dtype使用标准Python类型。另外NumPy提供它自己的数据类型。 - ndarray.itemsize
数组中每个元素的字节大小。例如,一个元素类型为float64的数组itemsiz属性值为8(=64/8),又如,一个元素类型为complex32的数组item属性为4(=32/8). - ndarray.data
包含实际数组元素的缓冲区,通常我们不需要使用这个属性,因为我们总是通过索引来使用数组中的元素。
一个例子
>>> from numpy import *
>>> a = arange(15).reshape(3, 5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int32'
>>> a.itemsize
4
>>> a.size
15
>>> type(a)
numpy.ndarray
>>> b = array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
numpy.ndarray
四.创建ndarray对象
- np.array([[1,2],[3,4]],dtype=userType)
使用array对象来封装python的列表或者元祖或者range对象. - 创建一维对象
np.linspace产生等差数列
np.logspace产生等比数列
np.arange产生等差数列 - 给定维数数组创建ndarray
np.ones全1数组
np.zeros全0数组
np.empty不做处理的数组,只负责开辟空间,比前面两个速度快
五.创建随机ndarray对象
随机值都是在区间[0,1)上
- 均匀分布
random.random(size=None)默认返回一个0~1之间的数字,可以指明维度序列来生成特定维度的随机值.
random.randint(low,high,size)返回一个int型数组,每个元素都在low,high之间.
np.random.rand,相当于random.random((d1,d2,d3)),只不过这个函数的参数可以是多个而不仅仅是一个元组. - 正态分布
np.random.randn
六.通用函数
通用函数的作用对象是数组中的每一个元素.
通用函数通常有一个out参数,如果带上这个参数就可以避免开辟新的内存空间.
七.广播broadcast
两个不同维度的数组相加
import numpy as np
a = np.arange(5)
b = np.arange(6).reshape(-1, 1)
def rep(a, c):
for i in range(a.ndim-1, -1, -1):
if a.shape[i] == c.shape[i]: continue
if a.shape[i] == 1:
a = a.repeat(c.shape[i], axis=i)
else:
raise Exception("dimention not match exception")
return a
def add(a, b):
if a.ndim>b.ndim: a, b = b, a
ashape = [1] * (b.ndim-a.ndim) + list(a.shape)
a = a.reshape(ashape)
cshape = [max(a.shape[i], b.shape[i]) for i in range(a.ndim)]
c = np.empty(cshape)
a = rep(a, c)
b = rep(b, c)
a = a.reshape(-1)
b = b.reshape(-1)
cc = c.reshape(-1)
for i in range(len(cc)):
cc[i] = a[i] + b[i]
return c
print(add(a, b))
print(a + b)