【数据结构】利用Python手把手带你自定义矩阵

举报
迷彩 发表于 2023/05/26 17:52:07 2023/05/26
【摘要】 前言什么是矩阵矩阵,Matrix。在数学上,矩阵是指纵横排列的二维数据表格,最早来自于方程组的系数及常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中。对于大多计算专业的同学来说,对矩阵应该都不陌生,在大学数学中一般都会开设一门线性代数的课程,在计算机中,线性代数是非常重要的一门学科,计算机大部分计算都是利用的线性代数里...

前言

什么是矩阵

矩阵,Matrix。在数学上,矩阵是指纵横排列的二维数据表格,最早来自于方程组的系数及常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中。


对于大多计算专业的同学来说,对矩阵应该都不陌生,在大学数学中一般都会开设一门线性代数的课程

,在计算机中,线性代数是非常重要的一门学科,计算机大部分计算都是利用的线性代数里面的矩阵运算,

故应用计算机的高速运算功能解决实际问题离不开线性代数的知识。线性代数在数学、物理学和技术学科中也有各种重要应用,因而它在各种代数分支中占居首要地位。线性代数所体现的几何观念与代数方法之间的联系,从具体概念抽象出来的公理化方法以及严谨的逻辑推证、巧妙的归纳综合等,对于强化人们的数学训练,增益科学智能是非常有用的。在计算机广泛应用的今天,计算机图形学、计算机辅助设计、计算机数据科学,密码学、虚拟现实等技术无不以线性代数作为其理论和算法基础的一部分。


随着科学的发展,我们不仅要研究单个变量之间的关系,还要进一步研究多个变量之间的关系,各种实际问题在大多数情况下可以线性化,而由于计算机的发展,线性化了的问题又可以被计算出来,线性代数正是解决这些问题的有力工具。


矩阵的运用


矩阵的应用极其广泛,在数学的基本应用中,矩阵的一个重要用途是解线性方程组。线性方程组中未知量的系数可以排成一个矩阵,加上常数项,则称为增广矩阵。另一个重要用途是表示线性变换,即是诸如f(x) 4x之类的线性函数的推广。设定基底后,某个向量v可以表示为m×1的矩阵,而线性变换f可以表示为行数为m的矩阵A,使得经过变换后得到的向量f(v)可以表示成Av的形式。矩阵的特征值和特征向量可以揭示线性变换的深层特性。除此之外,在大数据时代,矩阵在计算机数据科学中也是个不可或缺的工具。还有在物理中的线性变换及对称,量子态的线性组合,几何光学,电子学等等都是以矩阵来表示与计算


以上就是对矩阵的简单介绍,本文主要介绍使用Python实现自定义矩阵,与矩阵相关的运算这里就不再赘述,感兴趣的童鞋可以自行深入了解。接下来咱们就了解需要用到的Python相关知识。

自定义矩阵的前置知识


在Python中,以两个下划线开头的方法,如__init__()、__str__()、__doc__()、__new__()等,被称为魔术方法。魔术方法会自动执行,如果希望根据自己的程序定制特殊的功能的类,那么就需要对这些方法进行重写。


Python将所有以两个下划线开头的类保留为魔术方法。所以在定义类方法时,除了上述的魔术方法,建议不要以下划线为前缀。

本文会用到Python中魔术方法,所以我们需要对相关知识有所了解,下面是一些常见的魔术方法:

  1. __new__(cls[,...]):在一个对象实例化的时候调用第一个方法.他的第一个参数是这个类,其他的参数直接传递给__init__()方法.__new__()方法决定是否使用__init__().因为__new__()可以调用其他类的构造方法或者直接返回其他实例对象作为本类实例.如果__new__()没有返回实例对象,则,__init__()方法不会被调用.__new__()主要是用于继承一个不可变的类型,如一个tuple或者string.注:我们一般不会重写该方法

  2. __init__(self[,...]):构造器或者构造方法,相当于java和PHP中的构造函数,初始化类的时候被调用,用于对数据的初始化

  3. __del__(self):析构器或者析构方法,相当于php中的析构函数.当实例化对象被彻底销毁时被调用(实例化对象的所有指针都被销毁时被调用)

  4. __getitem__(self,key):定义获取容器中指定元素的行为,相当于 self[key]

  5. __setitem__(self, key, value):定义设置容器中指定元素的行为,相当于 self[key] = value

  6. __delitem__(self, key):定义删除容器中指定元素的行为,相当于 del self[key]

  7. __eq__(self, other):这个是比较操作符,定义等于号的行为:x == y 调用 x.__eq__(y)

  8. __add__(self, other):这个是算术运算符,定义加法的行为:+

  9. __sub__(self, other):这个是算术运算符,定义减法的行为:-

  10. __mul__(self, other):定义乘法的行为:*

  11. __truediv__(self, other):定义真除法的行为:/

  12. __len__(self):定义当被 len() 调用时的行为(一般返回容器类的长度)

这里只是介绍本文中可能用到的相关方法,还有很多其他魔术方法等你探索.


注:只有__new__()是类方法

实现自定义矩阵的流程

  1. 定义矩阵类,然后使用__init__()初始化矩阵的行数和列数

  2. 若类把某个属性定义为序列,那么__getitem__()可以输出某个元素的值

  3. 定义函数

  4. 定义矩阵的加法

  5. 在类中定义输出矩阵的函数

  6. 实例化类,验证实现的类是否正确

如下图所示:



如何实现矩阵

代码实现

引入copy,定义矩阵类的行数和列数:

import copy

class Matrix:

    def __init__(self, row, column, fill=0.0):
        self.shape = (row, column)
        self.row = row
        self.column = column
        self._matrix = [[fill] * column for i in range(row)]

在类中定义相关函数:

设置和获取矩阵的行和列元素的值:

    # 返回元素m(i, j)的值:  m[i, j]
    def __getitem__(self, index):
        if isinstance(index, int):
            return self._matrix[index - 1]
        elif isinstance(index, tuple):
            return self._matrix[index[0] - 1][index[1] - 1]

    # 设置元素m(i,j)的值为s:  m[i, j] = s
    def __setitem__(self, index, value):
        if isinstance(index, int):
            self._matrix[index - 1] = copy.deepcopy(value)
        elif isinstance(index, tuple):
            self._matrix[index[0] - 1][index[1] - 1] = value


实现矩阵的运算,将矩阵相加:两个矩阵能够相加的前提是两个矩阵的行列数一样,也就是维度一样:

    def __add__(self, N):
        '''加法'''
        # A + B
        assert N.shape == self.shape, "维度不匹配,不能相加"
        M = Matrix(self.row, self.column)
        for r in range(self.row):
            for c in range(self.column):
                M[r, c] = self[r, c] + N[r, c]
        return M


比较矩阵的维度,也就是比较矩阵的行数和列数:

    def __eq__(self, N):
        # A == B
        assert isinstance(N, Matrix), "注:类型不匹配,不能比较"
        return N.shape == self.shape  # 比较维度


打印矩阵:

    def show(self):
    #输出函数
        for r in range(self.row): #遍历
            for c in range(self.column):
                print(self[r + 1, c + 1], end='  ')
            print()


实例化类并验证定义的类:

if __name__ == '__main__':
    m = Matrix(3, 3, fill=0.0)
    n = Matrix(3, 3, fill=0.0)

    m[1] = [1., 2., 3.]
    m[2] = [4., 5., 6.]

    n[1] = [6., 7., 8.]
    n[2] = [9., 0., 1.]
    n[3] = [2., 3., 6.]

注:if __name__== '__main__':相当于C++和java中main()方法,也就是程序的入口;


进行矩阵的加法运算:

		p = m + n #矩阵加法
    m.show()
    print('------------分隔符-------------')
    p.show()
    print('------------分隔符-------------')
    print(p[1,1])

执行结果如下:


m = Matrix(3, 3, fill=0.0)
m[1] = [1., 2., 3.]
m[2] = [4., 5., 6.]
#这句定义的3行3列的矩阵,但是我们实际只是赋值了2行3列,fill=0.0的是给第三列空白位置填充0

平时我们使用到矩阵的时候都是使用python的numpy库提供的矩阵运算功能,很少需要自己去自定义,本文自定义矩阵是为了让自己更了解矩阵以及矩阵的基本实现原理.希望对你有所帮助.

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。