Numpy 中数据结构的核心是 n 维数组 n-dimensional array,简称 ndarray,需要注意的是数组中的元素都要属于同一个数据类型。

几个常用的 ndarray 的属性:ndarray.dtype,ndarray.shape,ndarray.ndim

几个常用的生成 ndarray 的方法:np.zeros( ),np.ones( ),np.zeros_like( ),np.ones_like( ),np.empty( ),np.arange( ),np.eye( ),np.identity( )

np.zeros(shape, dtype=float):shape 参数可以是一个自然数,也可以是二维元组,当元组中有三个参数时,后两个参数可以理解为 ndarray 的行数和列数,第一个参数为同样形状的 array 的个数。继续增加参数的个数的工作机制同上,都是对于后续的数组进行一个按照给定参数的量进行复制,np.ones( ) 工作机制类似。

np.zeros((2, 5, 3))

array([[[ 0., 0., 0.],

[ 0., 0., 0.],

[ 0., 0., 0.],

[ 0., 0., 0.],

[ 0., 0., 0.]],

[[ 0., 0., 0.],

[ 0., 0., 0.],

[ 0., 0., 0.],

[ 0., 0., 0.],

[ 0., 0., 0.]]])

np.zeros_like(),np.ones_like() 的参数为已有的一个 ndarray,会返回一个同形状的元素全 0 或全 1 的 ndarray。

np.empty() 生成一个占位的空数组,由于需要自行设置数组中的每一个值,因此要尽量少用。

np.arange() 的参数为一个整数,工作机制类似于 python 内建函数 range,但返回一个 ndarray。

np.arange(11)

array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

np.eye(N, M=none, k=0, dtype=) :N 为矩阵的行,M 为矩阵的列,如果 M 不指定则默认为 N x N 方阵,k 为 1 所在的对角线的位置

不指定列数:

np.eye(3) # 相当于 np.identity(3)

array([[ 1., 0., 0.],

[ 0., 1., 0.],

[ 0., 0., 1.]])

指定列数和 1 所在对角线位置:

np.eye(3, 4, 2)

array([[ 0., 0., 1., 0.],

[ 0., 0., 0., 1.],

[ 0., 0., 0., 0.]])

当 k ≥ M 时,为 0 矩阵:

np.eye(3, 4, 4)

array([[ 0., 0., 0., 0.],

[ 0., 0., 0., 0.],

[ 0., 0., 0., 0.]])

还可以通过 np.identity() 来创建单位矩阵

np.identity(4)

array([[ 1., 0., 0., 0.],

[ 0., 1., 0., 0.],

[ 0., 0., 1., 0.],

[ 0., 0., 0., 1.]])

ndarray 的索引和切片

一维 ndarray

一维 ndarray 的索引和切片与 list 类似,主要差别是可以通过索引和切片直接修改原 ndarray 中的值。同时, ndarray 的切片只是提供了原 ndarray 的一个局部视图 view 而不是原 ndarray 的一个拷贝,但对于切片的任何修改都会反映到原有的 ndarray 中去。后续大量数组的操作都是采用视图而非拷贝的原因是 Numpy 是为了操作大量数据而构建的,因此从性能的角度出发需要尽量的减少内存占用。

arr = np.arange(10)

arr[3: 8] = 10

arr_slice = arr[5: 8]

arr_slice

array([10, 10, 10])

对切片进行索引赋值操作会直接作用到原来的数组:

arr_slice[1] = 12

arr

array([0, 1, 2, 10, 10, 10, 12, 10, 8, 9])

如果确实需要进行复制,则可以通过显式的使用 arr[ 5: 8].copy() 来完成。

当对一维数组进行 arr.shape 查询时结果是诸如 (3, ) 的形式,这个看起来很怪异的形状在 Numpy 中称为 Rank 1 数组,对应的 arr.ndim 返回 1,在实际使用中应尽量避免这种数据结构,原因请参见这篇 rank 1 数组。

二维和高维 ndarray

二维数组的单个索引值得到的是一个一维数组:

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

arr2d[2]

array([7, 8, 9])

两个索引值则会获取相应位置的值:

arr2d[2, 2] # arr2d[2][2]

9

高维数组的索引机制与二维类似,即会根据提供的索引值逐次找到相应位置的数组或元素。

arr3d = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]])

arr3d.shape

(1, 4, 3)

单个索引值:

arr3d[0] # arr3d[1] will pop out an error

array([[ 1, 2, 3],

[ 4, 5, 6],

[ 7, 8, 9],

[10, 11, 12]])

两个索引值:

arr3d[0, 1] # shape = (3, )

array([4, 5, 6])

通过索引修改数组中的值:

arr3d[0, 1] = 1

arr3d

array([[[ 1, 2, 3],

[ 1, 1, 1],

[ 7, 8, 9],

[10, 11, 12]]])

也可以通过切片的形式访问数组中的元素:

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

arr2d[2, :2]

array([7, 8])

上面已经简单提到 Rank 1 数组这个对象,在实际应用中经常需要通过切片方式来获得数组的一个行或列中的数值并用于后续计算,而由下图可知由于这些数值可以通过采用不同的切片方式获得,此时为了避免产生 Rank 1 数组,要尽量使用双冒号切片形式进行选取。

Array slicing

布尔值索引

通过布尔值索引是一个非常重要的特征,可以通过这个操作快速选择满足一定特征的元素:

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

data = np.random.randn(7, 4)

data

array([[ 0.91937812, 0.37117872, -0.24042518, 0.30905519],

[-0.49121926, -1.0682015 , -0.0988304 , 1.43795767],

[ 1.11437469, 1.19878961, 0.00452662, 1.15337206],

[-1.1719382 , -0.13256179, -0.61995845, -0.99759886],

[-0.50507224, -2.60465047, -1.4235047 , 0.83859547],

[-1.26945164, -0.07747245, 1.50020684, -0.55767208],

[ 1.9902588 , -1.35701671, 1.28836883, 0.33033936]])

在数组索引中提供单个索引值时是针对行进行索引的,所以这里作为判断条件的 names 的行数必须和 data 的行数相等。

data[names == 'Bob']

array([[ 0.91937812, 0.37117872, -0.24042518, 0.30905519],

[-1.1719382 , -0.13256179, -0.61995845, -0.99759886]])

布尔值索引还可以和切片联合使用:

data[names == 'Bob', 2:]

array([[-0.24042518, 0.30905519],

[-0.61995845, -0.99759886]])

布尔值索引也可以同时用于修改符合某些条件量的值:

data[data < 0] = 0

data

array([[ 0.91937812, 0.37117872, 0. , 0.30905519],

[ 0. , 0. , 0. , 1.43795767],

[ 1.11437469, 1.19878961, 0.00452662, 1.15337206],

[ 0. , 0. , 0. , 0. ],

[ 0. , 0. , 0. , 0.83859547],

[ 0. , 0. , 1.50020684, 0. ],

[ 1.9902588 , 0. , 1.28836883, 0.33033936]])

需要注意的是:

通过布尔值索引进行数值选择时会返回一个符合判断条件的数值的拷贝,而如果在选择的同时给予赋值则在原地进行

逻辑运算符可以采用 & (and) 和 | (or),但不能直接使用 and 和 or

花式索引 Fancy indexing

花式索引在 Numpy 中是指用一个整数型数组作为索引值来对数组进行索引,并且按照指定的顺序以复制的方式返回索引值。

arr = np.empty((8, 4))

for i in range(8):

arr[i] = i

arr

array([[ 0., 0., 0., 0.],

[ 1., 1., 1., 1.],

[ 2., 2., 2., 2.],

[ 3., 3., 3., 3.],

[ 4., 4., 4., 4.],

[ 5., 5., 5., 5.],

[ 6., 6., 6., 6.],

[ 7., 7., 7., 7.]])

arr[[4, 3, 0, 6]]

array([[ 4., 4., 4., 4.],

[ 3., 3., 3., 3.],

[ 0., 0., 0., 0.],

[ 6., 6., 6., 6.]])

当在花式索引中提供两个整数数组时,返回的是被索引数组中以两个数组对应为元素为坐标的元素值:

arr = np.arange(32).reshape((8, 4))

arr

array([[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11],

[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23],

[24, 25, 26, 27],

[28, 29, 30, 31]])

arr[[1, 5, 7, 2], [0, 3, 1, 2]]

array([ 4, 23, 29, 10])

而如果想返回一个区域的值,则需要按照如下的方式先进行行索引,再对列进行排序:

arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]

array([[ 4, 7, 5, 6],

[20, 23, 21, 22],

[28, 31, 29, 30],

[ 8, 11, 9, 10]])

等同于 arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])],后续 [0, 3, 1, 2] 为对列进行重新排序。

数组的转置和轴的交换

二维数组的转置可以理解为矩阵的转置,并且还可以在转置的基础上做向量的点积运算。

arr = np.arange(15).reshape((3, 5))

arr

array([[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]])

arr.T # arr.transpose() 的一个特殊应用形式

array([[ 0, 5, 10],

[ 1, 6, 11],

[ 2, 7, 12],

[ 3, 8, 13],

[ 4, 9, 14]])

下面这个运算的结果是一个实对称矩阵,每一个对角线元素等于对应位置的行列元素的平方和,并且转置提供的依然是原有数组的一个视图,不改变原有数组的形状。

np.dot(arr.T, arr)

array([[125, 140, 155, 170, 185],

[140, 158, 176, 194, 212],

[155, 176, 197, 218, 239],

[170, 194, 218, 242, 266],

[185, 212, 239, 266, 293]])

当对高维数组施加 transpose( ) 时,其变换过程需要稍微做一些解释:对于一个数组来说,除了维数外,Numpy 还给它分配了轴,轴的序号按照各个轴在数组的 shape 元组中的索引位置来分配。针对下面这个例子来说,轴与形状的关系为 (2[ axis 0 ], 3[ axis 1 ], 4[ axis 2 ])。

arr = np.arange(24).reshape((2, 3, 4))

arr

array([[[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11]],

[[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23]]])

当按照如下所示的轴的顺序施加转置时,即将原来数组的 0 轴 和 1 轴交换,数组中的每一个元素都需要交换前两个坐标,也即转置后的形状将变为 (3, 2, 4)。例如 12 这个元素原来的索引坐标为 [1, 0, 0],在转置后交换其前两个索引坐标 [0, 1, 0]。

arr.transpose((1, 0, 2))

array([[[ 0, 1, 2, 3],

[12, 13, 14, 15]],

[[ 4, 5, 6, 7],

[16, 17, 18, 19]],

[[ 8, 9, 10, 11],

[20, 21, 22, 23]]])

类似的可以实现转置的操作还有一个方法 swapaxes( ),其参数为两个需要交换的轴,所以下面这个操作和上面的 arr.transpose((1, 0, 2))一致。

arr.swapaxes(0, 1)

array([[[ 0, 1, 2, 3],

[12, 13, 14, 15]],

[[ 4, 5, 6, 7],

[16, 17, 18, 19]],

[[ 8, 9, 10, 11],

[20, 21, 22, 23]]])

Universal Functions: 数组的快速元素级运算

Numpy 的强大之处就在于对于数值型变量的向量化 vectorization,避免了数值操作过程中大量的使用显式的 for 循环,universal functions 提供了一系列的元素级的操作,如:

np.square(some_array) 返回一个数组每一个元素的平方

np.maximum(array_A, array_B) 依次比较两个数组相同位置的元素并返回其中的最大值

np.where(condition, array_A, array_B) 相比 maximum 则可以进一步的返回符合某个判断条件的选择,判断逻辑为当条件满足时取 array_A,否则取 array_B。

arr_x = np.array([1.1, 1.2, 1.3, 1.4, 1.5])

arr_y = np.array([2.1, 2.2, 2.3, 2.4, 2.5])

cond = np.array([True, False, True, True, False])

np.where(cond, arr_x, arr_y) # 非向量化的实现方式为 [(x if c else y) for x, y, c in zip(arr_x, arr_y, cond)]

array([ 1.1, 2.2, 1.3, 1.4, 2.5])

np.where( ) 的参数中,第 2 个和第 3 个参数也可以是标量,常用于根据某个条件修改已有的数组中的值:

arr = np.random.randn(4, 4)

arr

array([[-1.22678789, -0.6000085 , -0.22466607, -0.85761133],

[ 0.75063805, 1.40825566, -0.72430125, -0.12158849],

[-0.83472573, 0.09379071, -0.1910247 , -2.38272863],

[-1.51568709, -0.65348116, -1.22607901, -1.76620207]])

np.where(arr>0, 2, -2)

array([[-2, -2, -2, -2],

[ 2, 2, -2, -2],

[-2, 2, -2, -2],

[-2, -2, -2, -2]])

np.where() 本身也可以做为备选参数以完成更加复杂的判断:

np.where(cond1 & cond2, 0, np.where(cond1, 1, np.where(cond2, 2, 3)))

数学和统计学计算

前面关于转置的部分简单提到了 Numpy 为数组分配了“轴”,这个概念的演示在很多 Numpy 的教程中都是以一些随机数或简单数值的数组来举例,使得理解这个概念的定义和意义变得困难。

事实上设定轴的现实意义在于实际应用中的数据都代表对于某些研究对象的特征的描述:在常用的单张二维数据表中一般单独的一行记录的是对于一个对象的不同特征的描述,而单独的一列则对应于同一个特征在不同对象中的记录。在二维数据表的基础上可以叠加多张数据表,这种组织形式的数据可以在后续的计算中使得数据可以沿某一个方向进行统计(例如计算加和,均值,方差等),由于这些统计的结果会在相应的方向上压缩相应的轴的长度,因此这些统计过程也常被称为缩减操作 Reduction operation。

在 Numpy 中 shape 和 axis 的关系是 shape 元组中的元素的索引位置就是相应的轴的名称,而shape 元组中的数值代表数组在相应轴上的数据的个数。一个数组的轴的数量 number of dimensions 称为维数,也称为秩 rank,这个 rank 可以通过数组中元素的分组形式来获得,也即 [ ] 的嵌套层数,或者通过 array.ndim 获得。注意这个定义和线性代数中的秩的定义是不同的,后者的查询方式为 np.linalg.matrix_rank(arr)。

关于 Numpy 轴的定义及计算可以参考 Lstyle 的这个笔记 Numpy 小记——有关 axis/axes 的理解,讲的非常好。个人认为更为直观的理解轴上的加总计算的方式就是可以想象这些数据沿着轴被串在一起的数字被汇总压缩为一个新的数字,因此在汇总后生成的新的数组的维数就会被降低。在应用中如果想保持原有的维数,可以使用关键字参数 keepdimes = True。

具体来说,在使用 ndarray.sum( ),ndarry.mean( ) 的时候,如果不指定轴,则是对整个数组内的所有数值进行加总和平均,而如果指定相应的轴,则会沿着轴的方向进行。

b = np.array([[[1,2,3,4],[5,6,7,8]],[[2,4,6,8],[3,5,7,9]],[[2,2,8,8],[1,0,5,8]]])

b # shape = (3, 2, 4)

array([[[1, 2, 3, 4],

[5, 6, 7, 8]],

[[2, 4, 6, 8],

[3, 5, 7, 9]],

[[2, 2, 8, 8],

[1, 0, 5, 8]]])

b.mean()

4.75

b.sum()

114

b.sum(axis=0) # shape = (2, 4)

array([[ 5, 8, 17, 20],

[ 9, 11, 19, 25]])

b.sum(axis=1) # shape = (3, 4)

array([[ 6, 8, 10, 12],

[ 5, 9, 13, 17],

[ 3, 2, 13, 16]])

b.sum(axis=2) # shape = (3, 2)

array([[10, 26],

[20, 24],

[20, 14]])

元素的唯一性和集合

对于一维数组,Numpy 还设有 numpy.unique( ) 这个方法,返回一个数组中的元素的集合,即无重复的返回数组中排序过的元素。

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

np.unique(names)

array(['Bob', 'Joe', 'Will'], dtype='

数组文件的读写

读写专门的 Numpy 文件:

写入硬盘:np.save('filename.npy', array_to_be_saved)

文件读入:np.load('filename.npy')

读写 txt 文件:

写入硬盘:np.savetxt('filename.txt', array_to_be_saved)

文件读入:np.loadtxt('filename.txt', delimiter=',')

线性代数相关操作

ndarray 的运算

我们一般很少直接的将 m 行 n 列的二维数组直接称为矩阵是因为这容易将其运算与矩阵运算混淆:在矩阵乘法中,m x n 的矩阵必须和 n x k 的矩阵才能进行。但在 ndarray 中这个要求则更加宽松:对于任意两个同形状的 n 维数组,其加 +,减 -,乘 *,除 / 运算都是基于相同位置的元素进行的,而标量和 ndarray 的运算是标量与每个元素进行相应的运算。

arr = np.array([[1, 2, 3], [4, 5, 6]])

arr * arr # the same as np.multiply(arr, arr)

array([[ 1, 4, 9],

[16, 25, 36]])

前面已经讲到在 Numpy 中,两个同形的数组之间的乘法发生在相同位置的两个元素之间。对应的矩阵相乘则需要借助下文的点积方法 np.dot(a, b)。除点积外,numpy.linalg 模块下集成了很多线性代数的操作,如矩阵求逆,QR 分解,特征值特征向量求解,SVD 分解等。

X = np.random.randn(4, 4)

mat = X.T.dot(X)

mat

array([[ 3.72779983, -1.3869418 , -0.93343812, -2.25143467],

[-1.3869418 , 5.29047179, 0.18681953, -2.91567006],

[-0.93343812, 0.18681953, 0.43223972, 0.40102812],

[-2.25143467, -2.91567006, 0.40102812, 4.82265242]])

np.linalg.inv(mat)

array([[ 21.4056399 , 13.58072833, 25.42913277, 16.08918057],

[ 13.58072833, 8.94242629, 15.78239186, 10.43411384],

[ 25.42913277, 15.78239186, 33.09360224, 18.66126891],

[ 16.08918057, 10.43411384, 18.66126891, 12.47497716]])

mat.dot(np.linalg.inv(mat))

array([[ 1.00000000e+00, -3.55271368e-15, 0.00000000e+00,

1.42108547e-14],

[ -2.84217094e-14, 1.00000000e+00, 7.10542736e-15,

-7.10542736e-15],

[ -8.88178420e-16, 8.88178420e-16, 1.00000000e+00,

-2.66453526e-15],

[ 0.00000000e+00, 7.10542736e-15, 0.00000000e+00,

1.00000000e+00]])

q, r = np.linalg.qr(mat)

r

array([[-4.66480052, 1.31147337, 1.08153305, 3.34017604],

[ 0. , -6.06042658, 0.03694935, 5.06062672],

[ 0. , 0. , -0.28772209, 0.4701318 ],

[ 0. , 0. , 0. , 0.03387203]])

Numpy 中的矩阵乘法

为了更清楚的表示输入输出,后续我会更改一下显示方式,回归原始的 Jupyter Notebook 中的状态。

import numpy as np

In [2]:

a = np.array([[1, 2, 3, 4],[5, 6, 7, 8]])

a

Out[2]:

array([[1, 2, 3, 4],

[5, 6, 7, 8]])

In [3]:

b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [11, 12, 13]])

b

Out[3]:

array([[ 1, 2, 3],

[ 4, 5, 6],

[ 7, 8, 9],

[11, 12, 13]])

Numpy 的矩阵乘法可以通过 np.dot(a, b) 或者 np.matmul(a, b) 来完成,当两个矩阵都是 2d array 时,结果相同的,而对于高维数组必须用 np.matmul(a, b) 来完成。

In [4]:

c = np.matmul(a, b)

c

Out[4]:

array([[ 74, 84, 94],

[166, 192, 218]])

In [5]:

np.dot(a,b)

Out[5]:

array([[ 74, 84, 94],

[166, 192, 218]])

需要注意的是, 对于一维 Numpy 数组来说,默认是按照行向量来存储的。如果需要通过其来构建列向量的时候,仅给予转置 arr.T 得到的还是行向量,需要采用 arr[ :, None] 或 arr.reshape((n, 1)) 来实现:

import numpy as np

In [2]:

a = np.array([1, 2, 3, 4]) # 1 dimension array

a

Out[2]:

array([1, 2, 3, 4])

In [3]:

a.T # Transpose does not change the shape of 1 dimension array

Out[3]:

array([1, 2, 3, 4])

In [4]:

a.reshape(4, 1) # Reshape is the right way to do

Out[4]:

array([[1],

[2],

[3],

[4]])

In [5]:

a[:, None] # or this one

Out[5]:

array([[1],

[2],

[3],

[4]])

python 双冒号切片_Numpy 学习笔记相关推荐

  1. Python基础教程-菜鸟教程学习笔记1

    Python基础教程-菜鸟教程学习笔记1 文章目录 Python基础教程-菜鸟教程学习笔记1 前言 Python 简介 1. 第一个Python程序 2. Python 中文编码 3. 基本语法 1) ...

  2. Python预测 数据分析与算法 学习笔记(特征工程、时间序列)

    微信公众号:数学建模与人工智能 GitHub - QInzhengk/Math-Model-and-Machine-Learning 第3章 探索规律 3.1 相关分析 相关关系是一种与函数关系相区别 ...

  3. Python可视化物理随机过程---pygame学习笔记2

    Python可视化物理随机过程-pygame学习笔记2 文章目录 Python可视化物理随机过程---pygame学习笔记2 一.扩散现象的简单的介绍 二.代码实现 三.运行代码的效果展示 四.总结 ...

  4. python中双冒号[::]切片的作用

    如:a=[1,2,3.4,5] 我们写:print(a[x:y:z])时,x表示切片起点,y表示切片终点,z表示步长.如果不指定x和y,则默认开始和最后(-1倒序除外),如果不指定z,则默认步长为1. ...

  5. python的基本数据结构_python学习笔记-基本数据结构

    Python 学习笔记-1 写在最前面,因为组内小伙伴要走,生信团队由原来的7个人,慢慢的变的只有我一个人了,需要紧急突击下python,因为有python的流程要交接维护 python 基本情况 代 ...

  6. 【Python基础】基础知识学习笔记

    Python学习笔记 基础知识 第1章 变量和简单数据类型 1.1 变量 1.1.1 变量的命名和使用 1.1.2 输出/输入 1.2 字符串 1.2.1 使用方法修改字符串的大小写 1.2.2 合并 ...

  7. python查看方法作用_python学习笔记1,新手小白也能看得懂

    这是酸菜在风变编程上学习python时积累的学习笔记,希望能帮到同样也在学习中的小伙伴.持续更新~ 第0关 Print()函数 (1)不带引号:让计算机读懂括号里的内容,打印最终的结果 例:print ...

  8. python矩阵左除_matlab学习笔记

    Matlab学习笔记 运算: 1.     算术运算(在矩阵意义下进行) +:要求矩阵同型,对应元素相加减,如果用标量和矩阵相加减,不同型就凉凉提示错误,那就将矩阵每个元素和数字相加减 -:同上 *: ...

  9. Python模块之Pandas模块学习笔记

    目录 一.模块的安装 二.数据结构 1. DataFrame的创建 2. DataFrame索引的修改 3. DataFrame数据信息查看 三.文件的读取和写入 1. 读取 2. 写入 四. 数据的 ...

最新文章

  1. 面试看缘分php,php测试姓名缘分指数
  2. Financiers Game CodeForces - 737D (博弈论,区间dp)
  3. windows7 设置 Local Settings权限为可以访问
  4. centos下svn与mysql_centos下SVN搭建
  5. 生成二维码接口,前端调用接口将二维码显示在页面上
  6. python数据结构的应用场景不包括,Python 数据结构学习
  7. android socket 代理服务器,Android 使用Socket进行服务器通信
  8. 佳能9100cdn故障_佳能 打印机故障代码大全
  9. IDEA中控制台中文乱码问题
  10. C接口与实现---之一
  11. MySQL数据表类型及文件结构
  12. 模拟爬虫下载QQ空间相册高清图片
  13. ModelSim SE简明操作指南
  14. java绘制五子棋棋盘
  15. 硬件工程师到底要会多少东西?
  16. maven 设置打包路径为模块_Maven项目的子模块不能打成jar包输出到lib目录
  17. 薄膜电容器在新能源领域应用和发展机遇
  18. ElasticSearch增删改查之python sort、scroll、scan
  19. php 二码合一支付_关于微信支付与支付宝支付前端这块二码合一的方法记录
  20. 详解诊断数据库ODX-F

热门文章

  1. 设计模式C++学习笔记之二(Proxy代理模式)
  2. Postgres 异常断电导致启动失败的解决方法
  3. 44个实用的Apache Web Server面试问题及答案
  4. 黑客攻防Redis拉锯战之Root提权
  5. 安全强化你的 Linux 服务器的七个步骤
  6. 【android studio】解决android studio drawable新建项目时只有一个drawable目录的问题
  7. 算法设计与分析--01背包问题(动态规划法解决)
  8. 安装Python3.5后,pip报错Fatal error in launcher: Unable to create process using ‘“‘解决方案
  9. The specified JRE installation does not exist异常的原因和解决办法
  10. 由于AsyncTask是一个单独的类,如何使OnPostExecute()的结果进入主要活动?