侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python numpy中矩阵的基本用法汇总

Python  /  管理员 发布于 7年前   271

Python矩阵的基本用法

mat()函数将目标数据的类型转化成矩阵(matrix)

1,mat()函数和array()函数的区别

Numpy函数库中存在两种不同的数据类型(矩阵matrix和数组array),都可以用于处理行列表示的数字元素,虽然他们看起来很相似,但是在这两个数据类型上执行相同的数学运算可能得到不同的结果,其中Numpy函数库中的matrix与MATLAB中matrices等价。

直接看一个例子:

import numpy as np a = np.mat('1 3;5 7')b = np.mat([[1,2],[3,4]])print(a)print(b)print(type(a))print(type(b))c = np.array([[1,3],[4,5]])print(c)print(type(c))

结果:

[[1 3]
 [5 7]]
[[1 2]
 [3 4]]
<class 'numpy.matrixlib.defmatrix.matrix'>
<class 'numpy.matrixlib.defmatrix.matrix'>
[[1 3]
 [4 5]]
<class 'numpy.ndarray'>

首先,mat() 函数与array()函数生成矩阵所需的数据格式有区别,mat()函数中数据可以为字符串以分号(;)分割或者为列表形式以逗号(,)分割,而array()函数中数据只能为后者形式。

其次,两者的类型不同,用mat函数转换为矩阵后才能进行一些线性代数的操作。

from numpy import * # 构建一个4*4的随机数组array_1 = random.rand(4,4)print(array_1)print(type(array_1))'''[[0.12681561 0.26644355 0.03582107 0.71475804] [0.01380711 0.85308305 0.37838406 0.83663897] [0.20034209 0.5736587 0.56692541 0.64008518] [0.97780979 0.129229 0.37688616 0.55341492]]  <class 'numpy.ndarray'> '''# 使用mat函数将数组转化为矩阵matrix_1 = mat(array_1)print(matrix_1)print(type(matrix_1))'''[[0.32538457 0.60674013 0.68625186 0.58957989] [0.26465813 0.93378939 0.12944934 0.95064032] [0.65683256 0.01352025 0.11932895 0.9361348 ] [0.11667241 0.16077876 0.50904118 0.44128675]] <class 'numpy.matrixlib.defmatrix.matrix'>'''

 2,mat()函数创建常见的矩阵

import numpy as np # 创建一个3*3的零矩阵,矩阵这里zeros函数的参数是一个tuple类型(3,3)data1 = np.mat(np.zeros((3,3)))print(data1)'''[[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]] '''# 创建一个2*4的1矩阵,默认是浮点型的数据,如果需要时int,可以使用dtype=intdata2 = np.mat(np.ones((2,4)))print(data2)'''[[1. 1. 1. 1.] [1. 1. 1. 1.]]''' # 这里使用numpy的random模块# random.rand(2,2)创建的是一个二维数组,但是需要将其转化为matrixdata3 = np.mat(np.random.rand(2,2))print(data3)'''[[0.62002668 0.55292404] [0.53018371 0.1548954 ]]''' # 生成一个3*3的0-10之间的随机整数矩阵,如果需要指定下界可以多加一个参数data4 = np.mat(np.random.randint(10,size=(3,3)))print(data4)'''[[0 4 1] [7 9 9] [9 0 4]]''' # 产生一个2-8之间的随机整数矩阵data5 = np.mat(np.random.randint(2,8,size=(2,5)))print(data5)'''[[4 6 3 3 4] [4 3 3 3 6]]''' # 产生一个2*2的对角矩阵data6 = np.mat(np.eye(2,2,dtype=int))print(data6)'''[[1 0] [0 1]]'''# 生成一个对角线为1,2,3的对角矩阵a1 = [1,2,3]a2 = np.mat(np.diag(a1))print(a2)'''[[1 0 0] [0 2 0] [0 0 3]]'''

2.1,zeros

zeros函数是生成指定维数的全0数组

>>myMat=np.zeros(3) ###生成一个一维的全0数组>>print(myMat)>>array([0.,0.,0.])  >>myMat1=np.zeros((3,2)) ####生成一个3*2的全0数组>>print(myMat)>>array([[0.,0.], [0.,0.] [0.,0.]])

2.2,ones

ones函数是用于生成一个全1的数组

>>onesMat=np.ones(3) ###1*3的全1数组>>print(onesMat)>>array([1.,1.,1.])   >>onesMat1=np.ones((2,3)) ###2*3的全1数组>>print(onesMat1)>>array([[1.,1.,1.],[1.,1.,1.]])

2.3,eye

eye函数用户生成指定行数的单位矩阵

>>eyeMat=np.eye(4) >>print(eyeMat)>>array([[1.,0.,0.,0.], [0.,1.,0.,0.], [0.,0.,1.,0.,], [0.,0.,0.,1.]])

2.4,full

numpy.full(shape,fill_value=num)用于创建一个自定义形状的数组,可以自己指定一个值,用它填满整个数组。

fill_value 用来填充的值,可以是数字,也可以是字符串

nd_test = np.full(shape=(2,3,4),fill_value='ai')print(nd_test) array([[['ai', 'ai', 'ai', 'ai'], ['ai', 'ai', 'ai', 'ai'], ['ai', 'ai', 'ai', 'ai']],  [['ai', 'ai', 'ai', 'ai'], ['ai', 'ai', 'ai', 'ai'], ['ai', 'ai', 'ai', 'ai']]], dtype='<U2')

2.5 nonzero()

nonzero函数是numpy中用于得到数组array中非零元素的位置(数组索引)函数。它的返回值是一个长度为a.ndim(数组a的轴数)的元组,元组的每个元素都是一个整数数组,其值为非零元素的下标在对应轴上的值。

只有a中非零元素才会有索引值,那些零值元素没有索引值,通过a[nonzero(a)]得到所有a中的非零值。

import numpy as np SS = [0,0,0,0] re = np.array(SS)print(SS)print(np.nonzero(re))'''[0, 0, 0, 0](array([], dtype=int64),)'''

a是一维数组(索引1和索引2的位置上元素的值非零)

>>> import numpy as np>>> a = [0,2,3]>>> b = np.nonzero(a)>>> b(array([1, 2], dtype=int64),)>>> np.array(b).ndim2

a是多维数组

from numpy import * b = array([[1,1,1,0,1,1],[1,1,1,0,1,0],[1,1,1,0,1,1]])print(b)c = nonzero(b)print(c)'''[[1 1 1 0 1 1] [1 1 1 0 1 0] [1 1 1 0 1 1]](array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2], dtype=int64),array([0, 1, 2, 4, 5, 0, 1, 2, 4, 0, 1, 2, 4, 5], dtype=int64))'''

解释一下:矩阵 b中,b[0,0] b[0,1],b[0,2],b[0,4],b[0,5],b[1,0],b[1,1],b[1,2],b[1,4],b[2,0],b[2,1],b[2,2],b[2,4],b[2,5]元素的值非零。

当使用布尔数组直接作为下标对象护着元组下标对象中有布尔数组时,都相当于用nonzero()将布尔数组转换成一组整数数组,然后使用整数数组进行下标计算。

nonzero(a)返回数组a中值不为零的元素的下标,它的返回值是一个长度为a.ndim(数组a的轴数)的元组,元组的每个元素都是一个整数数组,其值为非零元素的下标在对应轴上的值。例如对于1维布尔数组b1,nonzero(b1)所得到的是一个长度为1的元组,它表示b1[0]和b1[2]的值不为0(FALSE)。

import numpy as np b1 = np.array([True,False,True,False])res1 = np.nonzero(b1)print(res1)# (array([0, 2], dtype=int64),)

对于二维数组b2,nonzero(b2)所得到的是一个长度为2的元组,它的第0个元素是数组a中值不为0的元素的第0个轴的下标,第一个元素则是第1轴的下标,因此从下面得到的结果可知b2[0,0] , n2[0,2]和b2[1,0]的值不为0:

b2 = np.array([[True,False,True],[True,False,False]])res2 = np.nonzero(b2)print(res2)# (array([0, 0, 1], dtype=int64), array([0, 2, 0], dtype=int64))

当布尔数组直接做维下标时,相当于使用由nonzero()转换之后的元组作为下标对象:

b3 = np.arange(3*4*5).reshape(3,4,5)res3 = b3[np.nonzero(b2)]print(res3)'''[[ 0 1 2 3 4] [10 11 12 13 14] [20 21 22 23 24]]'''

3,常见的矩阵运算

3.1,矩阵相乘(*)

就是矩阵的乘法操作,要求左边矩阵的列和右边矩阵的行数要一致

from numpy import *''' 1*2 的矩阵乘以2*1 的矩阵 得到1*1 的矩阵''' a1 = mat([1,2])print(a1)a2 = mat([[1],[2]])print(a2)a3 = a1*a2print(a3)'''[[1 2]][[1] [2]][[5]]'''

3.2,矩阵点乘(multiply)

矩阵点乘则要求矩阵必须维数相等,即M*N维矩阵乘以M*N维矩阵

from numpy import *''' 矩阵点乘为对应矩阵元素相乘''' a1 = mat([1,1])print(a1)a2 = mat([2,2])print(a2)a3 = multiply(a1,a2)print(a3)'''[[1 1]][[2 2]][[2 2]]'''  a1 = mat([2,2])a2 = a1*2print(a2)# [[4 4]]

3.3,矩阵求逆变换(.I)

from numpy import *''' 矩阵求逆变换:求矩阵matrix([[0.5,0],[0,0.5]])的逆矩阵''' a1 = mat(eye(2,2)*0.5)print(a1)a2 = a1.Iprint(a2)'''[[0.5 0. ] [0. 0.5]][[2. 0.] [0. 2.]]'''

3.4,矩阵求转置(.T)

from numpy import *'''矩阵的转置''' a1 = mat([[1,1],[0,0]])print(a1)a2 = a1.Tprint(a2)'''[[1 1] [0 0]][[1 0] [1 0]] '''

3.5,求矩阵对应列行的最大值,最小值,和。

计算每一列,行的和

from numpy import *'''计算每一列,行的和''' a1 = mat([[1,1],[2,3],[4,5]])print(a1)# 列和,这里得到的是1*2的矩阵a2=a1.sum(axis=0)print(a2)'''[[7 9]]'''# 行和,这里得到的是3*1的矩阵a3=a1.sum(axis=1)print(a3)'''[[2] [5] [9]] '''# 计算第一行所有列的和,这里得到的是一个数值a4=sum(a1[1,:])print(a4)'''5'''

计算最大,最小值和索引

from numpy import *'''计算每一列,行的和''' a1 = mat([[1,1],[2,3],[4,5]])print(a1)'''[[1 1] [2 3] [4 5]]'''# 计算a1矩阵中所有元素的最大值,这里得到的结果是一个数值maxa = a1.max()print(maxa) #5# 计算第二列的最大值,这里得到的是一个1*1的矩阵a2=max(a1[:,1])print(a2) #[[5]]# 计算第二行的最大值,这里得到的是一个一个数值maxt = a1[1,:].max()print(maxt) #3# 计算所有列的最大值,这里使用的是numpy中的max函数maxrow = np.max(a1,0)print(maxrow) #[[4 5]]# ;//计算所有行的最大值,这里得到是一个矩阵maxcolumn = np.max(a1,1)print(maxcolumn)'''[[1] [3] [5]]'''# 计算所有列的最大值对应在该列中的索引maxindex = np.argmax(a1,0)print(maxindex) #[[2 2]]# 计算第二行中最大值对应在改行的索引tmaxindex = np.argmax(a1[1,:])print(tmaxindex) # 1

3.6,矩阵的分隔和合并 (vstack  hstack)

矩阵的分割,同列表和数组的分割一致

from numpy import *''' 矩阵的分隔,同列表和数组的分隔一致''' a = mat(ones((3,3)))print(a)# 分隔出第二行以后的行和第二列以后的列的所有元素b = a[1:,1:]print(b)'''[[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]][[1. 1.] [1. 1.]]'''

矩阵的合并

from numpy import * a = mat(ones((2,2)))print(a)b = mat(eye(2))print(b)# 按照列和并,即增加行数c = vstack((a,b))print(c)# 按照行合并,即行数不变,扩展列数d = hstack((a,b))print(d)'''[[1. 1.] [1. 1.]] [[1. 0.] [0. 1.]] [[1. 1.] [1. 1.] [1. 0.] [0. 1.]] [[1. 1. 1. 0.] [1. 1. 0. 1.]]'''

3.7,矩阵,列表,数组的转换

列表可以修改,并且列表中元素可以使不同类型的数据,如下:

1li =[[1],'hello',3]

numpy中数组,同一个数组中所有元素必须为同一个类型,有几个常见的属性:

from numpy import * a=array([[2],[1]])print(a )dimension=a.ndimm,n=a.shape# 元素总个数number=a.sizeprint(number)# 2# 元素的类型str=a.dtypeprint(str)# int32

numpy中的矩阵也有与数组常见的几个属性,他们之间的转换如下:

from numpy import * # 列表a1 = [[1,2],[3,2],[5,2]]# 将列表转化为二维数组a2 = array(a1)# 将列表转化成矩阵a3 = mat(a1)# 将矩阵转化成数组a4 = array(a3)# 将矩阵转换成列表a5=a3.tolist()# 将数组转换成列表a6=a2.tolist()print(type(a1))print(type(a2))print(type(a3))print(type(a4))print(type(a5))print(type(a6))'''<class 'list'><class 'numpy.ndarray'><class 'numpy.matrixlib.defmatrix.matrix'><class 'numpy.ndarray'><class 'list'><class 'list'>'''

注意:当列表为一维的时候,将他们转换成数组和矩阵后,再通过tolist()转换成列表是不相同的,这里需要做一些小小的修改,如下:

from numpy import * a1=[1,2,3]print(a1)print(type(a1))a2=array(a1)print(a2)print(type(a2))a3=mat(a1)print(a3)print(type(a3))'''[1, 2, 3]<class 'list'>[1 2 3]<class 'numpy.ndarray'>[[1 2 3]]<class 'numpy.matrixlib.defmatrix.matrix'> '''a4=a2.tolist()print(a4)print(type(a4))a5=a3.tolist()print(a5)print(type(a5))'''[1, 2, 3]<class 'list'>[[1, 2, 3]]<class 'list'>''' a6=(a4 == a5)print(a6)print(type(a6))a7=(a4 is a5[0])print(a7)print(type(a7))'''False<class 'bool'>False<class 'bool'>'''

矩阵转换成数值,存在以下一种情况:

from numpy import * dataMat=mat([1])print(dataMat)print(type(dataMat))'''[[1]]<class 'numpy.matrixlib.defmatrix.matrix'>''' # 这个时候获取的就是矩阵的元素的数值,而不再是矩阵的类型val=dataMat[0,0]print(val)print(type(val))'''1<class 'numpy.int32'>'''

 4, matrix.getA()

getA()是numpy的一个函数,作用是将矩阵转成一个ndarray,getA()函数和mat()函数的功能相反,是将一个矩阵转化为数组。

如果不转,矩阵的每个元素将无法取出,会造成越界的问题,其具体解释如下:

matrix.getA()   Return self as an ndarray object.  Equivalent to np.asarray(self)Parameters: NoneReturns: __ret_: ndarray  self as an ndarray

举例如下:

>>> x = np.matrix(np.arange(12).reshape((3,4))); xmatrix([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])>>> x.getA()array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])

那么为什么需要转换呢?

因为在画出数据集合的函数中,代码如下(取自机器学习实战Logistic回归最佳拟合直线的函数)

def plotBestFit(weights): weights = weights.getA() ... for i in range(n): #分类 if int(labelMat[i]) == 1:  xcord1.append(dataArr[i, 1])  ycord1.append(dataArr[i, 2]) else:  xcord2.append(dataArr[i, 1])  ycord2.append(dataArr[i, 2])

在这个代码,我们需要取出其中每一行每一列的值

如果是矩阵的话,我们测试一下:

>>> bmatrix([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]])>>> b[1][1]Traceback (most recent call last): File "<stdin>", line 1, in <module> File "D:\Python\lib\site-packages\numpy\matrixlib\defmatrix.py", line 284, in __getitem__ out = N.ndarray.__getitem__(self, index)IndexError: index 1 is out of bounds for axis 0 with size 1>>>>>> len(b[1])1>>> len(b[1][0])1

可以发现我们取出矩阵的一行大小只有1,如果你使用b[1][1],b[1][2]之类的就会越界

当我们转为np.array类型时

>>> carray([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]])>>> len(c[1])4>>> c[1][1]2>>>

可以看出,我们可以取出任何一个值。

Python矩阵的切片

1,行操作

li = [[1,1],[1,3],[2,3],[4,4],[2,4]]from numpy import * a = [[1,2],[3,4],[5,6]]a = mat(a)# 打印整个矩阵print(a[0:])'''[[1 2] [3 4] [5 6]] ''' # 打印矩阵E从1行开始到末尾行的内容print(a[1:])'''[[3 4] [5 6]] ''' # 表示打印矩阵E 从1行到3行的内容print(a[1:3])'''[[3 4] [5 6]] '''

2,列操作

li = [[1,1],[1,3],[2,3],[4,4],[2,4]]from numpy import *mat = mat(li)# 在整个矩阵的基础下,打印1列(指的是序列为1的列print(mat[:,0])'''[[1] [1] [2] [4] [2]]'''# 在矩阵的1行到2行([1,3)) 的前提下打印两列# 2 列不是指两列,而是序号为2的列print(mat[1:3,1])'''[[3] [3]] '''

Python numpy库其他函数用法

Numpy 的tile函数用法

  tile函数位于Python模块numpy.lib.shape_base中,他的功能是重复某个数组,比如 tile(A,reps),功能是将数组A重复reps次,构成一个新的数组。

1,函数的定义与说明

  函数格式为   tile(A,reps)

  A和reps 都是array_like

  A的类型众多,几乎所有类型都可以:array  list  tuple  dict  matrix 以及基本数据类型Int string  float 以及bool类型。

  reps 的类型也很多,可以是tuple  list  dict  array int  bool  但不可以是float   string  matrix类型。

2,示例

>>> a = np.array([0, 1, 2]) >>> np.tile(a, 2) array([0, 1, 2, 0, 1, 2]) >>> np.tile(a, (2, 2)) array([[0, 1, 2, 0, 1, 2],  [0, 1, 2, 0, 1, 2]]) >>> np.tile(a, (2, 1, 2)) array([[[0, 1, 2, 0, 1, 2]],  [[0, 1, 2, 0, 1, 2]]])  >>> b = np.array([[1, 2], [3, 4]]) >>> np.tile(b, 2) array([[1, 2, 1, 2],  [3, 4, 3, 4]]) >>> np.tile(b, (2, 1)) array([[1, 2],  [3, 4],  [1, 2],  [3, 4]])  >>> c = np.array([1,2,3,4]) >>> np.tile(c,(4,1)) array([[1, 2, 3, 4],  [1, 2, 3, 4],  [1, 2, 3, 4],  [1, 2, 3, 4]])
from numpy import * code1 = tile(1,2)print(code1)# [1 1] code2 = tile((1,2,3),3)print(code2)# [1 2 3 1 2 3 1 2 3] a = [1,3,4]code3 = tile(a,[2,3])print(code3)'''[[1 3 4 1 3 4 1 3 4] [1 3 4 1 3 4 1 3 4]] '''

Numpy  范数的用法

顾名思义,linalg = linear + algebralinalg = linear + algebra , norm则表示范数,首先需要注意的是范数是对向量(或者矩阵)的度量,是一个标量(scalar):

np.linalg.norm(求范数):linalg=linear(线性)+algebra(代数)

首先:help(np.linalg.norm) 查看其文档:

norm(x, ord=None, axis=None, keepdims=False)

这里我们只对常用设置进行说明,x表示要度量的向量,ord表示范数的种类,axis表示向量的计算方向,keepdims表示设置是否保持维度不变。

用法:

import numpy as np a=np.array([[complex(1,-1),3],[2,complex(1,1)]]) print(a)  print(np.linalg.norm(a,ord=2) ) #计算矩阵2的范数  print(np.linalg.norm(a,ord=1) ) #计算矩阵1的范数  print(np.linalg.norm(a,ord=np.inf) ) #计算矩阵无穷的范数

示例:

import numpy as npx = np.array([5,7])np.linalg.norm(x)8.602325267042627np.linalg.norm(x,ord=2)8.602325267042627np.linalg.norm(x,ord=1)12.0np.linalg.norm(x,ord=np.inf)7.0

范数理论告诉我们,一范数 >=  二范数  >=  无穷范数

参考文献:https:///article/124939.htm

https:///article/156112.htm

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家的支持。


  • 上一条:
    详解Python logging调用Logger.info方法的处理过程
    下一条:
    python读取csv和txt数据转换成向量的实例
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客