总目标

Python语法基础也学了挺久的了。但一直没有什么练习的机会。突然灵光一现,毕竟我是学数学的。不如用Python基础语法来实现数学里的一些东西吧。奈何数分实现难度太高,仅依靠我学的一点点Python语法皮毛,根本无从下手。这时我想起了高代。作为高代知识的重要载体,矩阵有着许许多多的性质,而这些性质大部分与数的运算有关。这便于用基础程序实现。
本专题的总目标就是:利用Python基础语法,实现一个矩阵类,能够进行矩阵的加、减、乘、逆,数乘、转置、化阶梯型等各种矩阵运算。

本节小目标

  • 定义矩阵类(Matrix)
  • 让print能够打印矩阵对象
  • 能够进行矩阵的加、减、数乘

定义矩阵类

好吧。首先要定义出一个矩阵类来。类名是Matrix。

class Matrix(object):

定义一个类,首先要想好构造函数。
让我们来看看矩阵的定义:

由 m × n 个数域P中的数组成的m行n列数表

从中我们可以提取出三个要素:

  1. m行
  2. n列
  3. 数表

所以我们的构造函数的三个参数也分别是这三个要素:

def __init__(self,m:int,n:int,matrix=None):

其中m是矩阵的行数,类型一定要是int.n是矩阵的列数,类型为int.matrix需要是一个二维列表,默认可以不传入。

构造函数的功能大概是:
传入m,n,如果传入了一个由m个长度为n的列表组成的二维列表matrix,那么设置这个矩阵对象的m属性为mn属性为nmatrix属性为matrix.如果没有传入matrix,那么就自动创建一个m×n的元素全为1的矩阵,设置m,n,matrix等属性。
既然框架已经有了。那么就用代码开始实践吧!

init()
   class Matrix(object):
    """矩阵类"""

    def __init__(self, m: int, n: int, matrix=None):
        """
        m:行数 n:列数
        matrix:二维列表
        """
        if matrix:  # 传入了matrix
            if is_mn_matrix(matrix, m, n):  # matrix为正确的m×n二维列表
                self.m = m
                self.n = n
                self.matrix = matrix
                return
            else:
                print(f"矩阵形状错误,将默认创建{m}×{n}全1矩阵...")

        # 没传入matrix
        self.m = m
        self.n = n
        self.matrix = [[1 for i in range(n)] for j in range(m)]  # 创建默认全一矩阵
is_mn_matrix()

其中is_mn_matrix这个判断函数我们在类外写就行了。

def is_mn_matrix(matrix: list[list], m:int, n:int):
    """判断二维列表是否是m×n型矩阵"""
    yes = True  # 设置标志
    if len(matrix) == m:  # 行数确实是m
        for i in range(m):
            if len(matrix[i]) != n:  # 如果有列数不是n,就返回错
                yes = False
                break
    else:  # 行数不是m,返回错
        yes = False
    return yes

写到这里,我们的第一步就已经完成了。我们成功编写了Matrix类的构造函数。试验一下。

if __name__ == "__main__":  #试验代码入口

    a = Matrix(3, 3, [[1, 2, 3], [2, 3, 4], [5, 6, 7]])
    print(a)
    print(a.matrix)
    b = Matrix(3, 3, [[2, 2], [4, 4]])
    print(b)
    print(b.matrix)
    c = Matrix(3, 3)
    print(c)
    print(c.matrix)

运行结果没有问题:

<__main__.Matrix object at 0x0000019F22595DE0>
[[1, 2, 3], [2, 3, 4], [5, 6, 7]]
矩阵形状错误,将默认创建3×3全1矩阵...
<__main__.Matrix object at 0x0000019F22595CC0>
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
<__main__.Matrix object at 0x0000019F22595C60>
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]

让print能够打印矩阵对象

上面的实验过程中,我们发现将Matrix对象传入print()函数,只会打印出极其难看的

<__main__.Matrix object at 0x0000019F22595C60>

我们当然希望打印一个矩阵,能直接看出它的形状和各元素排列。

str()

这个时候魔法方法__str__ 就能派上用场了。
废话不多说,直接上代码:

    def __str__(self):
        """打印矩阵"""
        string = f"{self.m}×{self.n}矩阵:\n"  #行列信息

        for row in self.matrix:
            for item in row:
                string += f"{int(item):<3}  "   #每个元素占3位,左对齐
            string += "\n"	# 每行末换行
        return string  #string就是print将打印的东西

这段代码本质上就是遍历二维列表的元素,所以也没有什么难度。
但由于学的东西还是太少了,完全不知道让小数怎么对齐得好看一点,所以我选择直接把元素以整型的形式打印出来。注意matrix属性里的元素是小数就还是小数,不会因为我打印出来是整数就会变。
试验一下:

if __name__ == "__main__":
    a = Matrix(3, 3, [[1.1, 2, 3], [2.2, 3, 4], [5.5, 6, 7]])
    print(a)
    print(a.matrix)

运行结果挺可以的:

3×3矩阵:
1   2   3   
2   3   4   
5   6   7   

[[1.1, 2, 3], [2.2, 3, 4], [5.5, 6, 7]]

能够进行矩阵的加、减、数乘

矩阵加减

之所以选择先实现矩阵的加减,是因为矩阵加减的规则异常简单,只需要循环遍历,对应位置的元素加减就行。
我们希望能够编写一个函数,其使用类似于:

c=a.add(b)  #将矩阵b加到a上,并能返回结果(新的Matrix对象)给c,但不改变矩阵a
copy()

要实现对a的元素进行运算但又不修改a,就需要能够复制矩阵a对象为new。直接new=a是不行的。因为a.matrix是可变数据类型列表,所以我们的Matrix也可以算是可变数据类型,所以a,new的修改是同步的。不妨写一个copy方法。

    def copy(self):
        """复制"""
        new = Matrix(self.m, self.n)
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] = self.matrix[i][j]
        return new

有了copy,就能实现对象复制了。

get_size()

需要注意,只有同型矩阵才能进行加减。我们不妨再实现一个get_size方法来获取矩阵的大小。

    def get_size(self):
        """返回矩阵大小"""
        return self.m, self.n

异常之简单。

add/minus

有了copyget_size的准备工作,现在让我们来实现矩阵的加法与减法吧。(逻辑一模一样,只是个正负号的差别。)

    def add(self, other: "Matrix"):
        """加other矩阵"""

        if self.get_size() != other.get_size():
            print("矩阵大小不匹配!")
            return

        new = self.copy()
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] += other.matrix[i][j]  # 对应元素相加
        return new
    def minus(self, other: "Matrix"):
        """减other矩阵"""

        if self.get_size() != other.get_size():
            print("矩阵大小不匹配!")
            return

        new = self.copy()
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] -= other.matrix[i][j]  # 对应元素相减
        return new

试验:

if __name__ == "__main__":
    a = Matrix(3, 3, [[1, 2, 3], [2, 3, 4], [5, 6, 7]])
    b=Matrix(3, 3, [[2, 3, 3], [3, 3, 3], [5, 2, 0]])
    print(a)
    print(b)
    c=a.add(b)
    print(a)
    print(c)
    d=Matrix(2,2)
    e=a.add(d)

运行结果:

3×3矩阵:    #a
1   2   3   
2   3   4   
5   6   7   

3×3矩阵:    #b
2   3   3   
3   3   3   
5   2   0   

3×3矩阵:     #加完后a不变
1   2   3   
2   3   4   
5   6   7   

3×3矩阵:     #c=a.add(b)
3   5   6   
5   6   7   
10  8   7   

矩阵大小不匹配!     #不同型尝试相加

no problem!

数乘

数乘就更简单了:只需要每个元素都乘k倍就行

k_multipy()
    def k_multipy(self, k):
        """k数乘"""
        new = self.copy()
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] *= k
        return new

试验:

if __name__ == "__main__":
    a = Matrix(3, 3, [[1, 2, 3], [2, 3, 4], [5, 6, 7]])
    b=a.k_multipy(2)
    print(a)
    print(b)

运行结果:

3×3矩阵:   #a
1   2   3   
2   3   4   
5   6   7   

3×3矩阵:   #b=a.k_multipy(2)
2   4   6   
4   6   8   
10  12  14  

代码汇总

好了,本节的小目标成功达成!

def is_mn_matrix(matrix: list[list], m: int, n: int):
    """判断二维列表是否是m×n型矩阵"""
    yes = True  # 设置标志
    if len(matrix) == m:  # 行数确实是m
        for i in range(m):
            if len(matrix[i]) != n:  # 如果有列数不是n,就返回错
                yes = False
                break
    else:  # 行数不是m,返回错
        yes = False
    return yes


class Matrix(object):
    """矩阵类"""

    def __init__(self, m: int, n: int, matrix=None):
        """
        m:行数 n:列数
        matrix:二维列表
        """
        if matrix:  # 传入了matrix
            if is_mn_matrix(matrix, m, n):  # matrix为正确的m×n二维列表
                self.m = m
                self.n = n
                self.matrix = matrix
                return
            else:
                print(f"矩阵形状错误,将默认创建{m}×{n}全1矩阵...")

        # 没传入matrix
        self.m = m
        self.n = n
        self.matrix = [[1 for i in range(n)] for j in range(m)]  # 创建默认全一矩阵

    def get_size(self):
        """返回矩阵大小"""
        return self.m, self.n
        
    def add(self, other: "Matrix"):
        """加other矩阵"""

        if self.get_size() != other.get_size():
            print("矩阵大小不匹配!")
            return

        new = self.copy()
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] += other.matrix[i][j]  # 对应元素相加
        return new

    def minus(self, other: "Matrix"):
        """减other矩阵"""

        if self.get_size() != other.get_size():
            print("矩阵大小不匹配!")
            return

        new = self.copy()
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] -= other.matrix[i][j]  # 对应元素相减
        return new

    def k_multipy(self, k):
        """k数乘"""
        new = self.copy()
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] *= k
        return new

    def copy(self):
        """复制"""
        new = Matrix(self.m, self.n)
        for i in range(self.m):
            for j in range(self.n):
                new.matrix[i][j] = self.matrix[i][j]
        return new

    def __str__(self):
        """打印矩阵"""
        string = f"{self.m}×{self.n}矩阵:\n"  # 行列信息

        for row in self.matrix:
            for item in row:
                string += f"{int(item):<3} "  # 每个元素占3位,左对齐
            string += "\n"  # 每行末换行
        return string  # string就是print将打印的东西
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐