NumPy-源码解析-三十一-

37 阅读1小时+

NumPy 源码解析(三十一)

.\numpy\numpy\ma\timer_comparison.py

# 导入用于计时的模块
import timeit
# 导入 reduce 函数,用于对序列进行累积计算
from functools import reduce

# 导入 NumPy 库,并指定别名 np
import numpy as np
# 导入 NumPy 的核心模块 fromnumeric
import numpy._core.fromnumeric as fromnumeric

# 导入 NumPy 的测试模块中的错误消息构建函数
from numpy.testing import build_err_msg

# 设置常数 pi 为 NumPy 中定义的圆周率值
pi = np.pi

# 定义 ModuleTester 类,用于测试指定模块中的函数
class ModuleTester:
    def __init__(self, module):
        # 初始化类的实例,传入要测试的模块
        self.module = module
        # 以下是从模块中获取和设置的一系列函数和属性,用于后续的测试操作
        self.allequal = module.allequal
        self.arange = module.arange
        self.array = module.array
        self.concatenate = module.concatenate
        self.count = module.count
        self.equal = module.equal
        self.filled = module.filled
        self.getmask = module.getmask
        self.getmaskarray = module.getmaskarray
        self.id = id
        self.inner = module.inner
        self.make_mask = module.make_mask
        self.masked = module.masked
        self.masked_array = module.masked_array
        self.masked_values = module.masked_values
        self.mask_or = module.mask_or
        self.nomask = module.nomask
        self.ones = module.ones
        self.outer = module.outer
        self.repeat = module.repeat
        self.resize = module.resize
        self.sort = module.sort
        self.take = module.take
        self.transpose = module.transpose
        self.zeros = module.zeros
        self.MaskType = module.MaskType
        # 尝试获取 umath 属性,如果不存在则使用 module.core.umath
        try:
            self.umath = module.umath
        except AttributeError:
            self.umath = module.core.umath
        # 初始化测试用例名称列表
        self.testnames = []
    def assert_array_compare(self, comparison, x, y, err_msg='', header='',
                             fill_value=True):
        """
        Assert that a comparison of two masked arrays is satisfied elementwise.

        """
        # 将输入的两个数组 x 和 y 填充为非掩码状态的数组
        xf = self.filled(x)
        yf = self.filled(y)
        # 使用 mask_or 方法生成 x 和 y 的掩码,并合并
        m = self.mask_or(self.getmask(x), self.getmask(y))

        # 使用填充后的数组 xf 和 yf 创建新的 MaskedArray 对象,再次填充,使用 fill_value 参数
        x = self.filled(self.masked_array(xf, mask=m), fill_value)
        y = self.filled(self.masked_array(yf, mask=m), fill_value)

        # 如果 x 和 y 的 dtype 不是 "O"(即不是对象型),将它们转换为 np.float64 类型
        if (x.dtype.char != "O"):
            x = x.astype(np.float64)
            # 如果 x 是 ndarray 类型且大小大于 1,则将其中的 NaN 值替换为 0
            if isinstance(x, np.ndarray) and x.size > 1:
                x[np.isnan(x)] = 0
            # 如果 x 是 NaN,则将其替换为 0
            elif np.isnan(x):
                x = 0

        # 类似地处理 y
        if (y.dtype.char != "O"):
            y = y.astype(np.float64)
            if isinstance(y, np.ndarray) and y.size > 1:
                y[np.isnan(y)] = 0
            elif np.isnan(y):
                y = 0

        try:
            # 检查 x 和 y 的形状是否相同,或其中一个是标量
            cond = (x.shape == () or y.shape == ()) or x.shape == y.shape
            # 如果形状不匹配,生成错误消息
            if not cond:
                msg = build_err_msg([x, y],
                                    err_msg
                                    + f'\n(shapes {x.shape}, {y.shape} mismatch)',
                                    header=header,
                                    names=('x', 'y'))
                assert cond, msg

            # 进行比较操作 comparison(x, y)
            val = comparison(x, y)

            # 如果存在掩码并且 fill_value 为 True,则创建一个 MaskedArray 对象
            if m is not self.nomask and fill_value:
                val = self.masked_array(val, mask=m)

            # 如果 val 是布尔值,判断其条件并设置 reduced 列表
            if isinstance(val, bool):
                cond = val
                reduced = [0]
            else:
                reduced = val.ravel()
                cond = reduced.all()
                reduced = reduced.tolist()

            # 如果条件不满足,计算不匹配百分比,并生成错误消息
            if not cond:
                match = 100-100.0*reduced.count(1)/len(reduced)
                msg = build_err_msg([x, y],
                                    err_msg
                                    + '\n(mismatch %s%%)' % (match,),
                                    header=header,
                                    names=('x', 'y'))
                assert cond, msg

        # 捕获 ValueError 异常,生成错误消息
        except ValueError as e:
            msg = build_err_msg([x, y], err_msg, header=header, names=('x', 'y'))
            raise ValueError(msg) from e

    def assert_array_equal(self, x, y, err_msg=''):
        """
        Checks the elementwise equality of two masked arrays.

        """
        # 调用 assert_array_compare 方法进行两个数组 x 和 y 的元素比较
        self.assert_array_compare(self.equal, x, y, err_msg=err_msg,
                                  header='Arrays are not equal')

    @np.errstate(all='ignore')
    def test_0(self):
        """
        Tests creation

        """
        # 创建包含浮点数和特定掩码的 numpy 数组 x,并使用 self.masked_array 方法创建 MaskedArray 对象
        x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.])
        m = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
        xm = self.masked_array(x, mask=m)
        # 访问 xm 的第一个元素
        xm[0]

    @np.errstate(all='ignore')
    @np.errstate(all='ignore')
    # 使用 NumPy 的错误状态管理器,忽略所有错误
    def test_1(self):
        """
        Tests creation

        """
        # 创建测试数据
        x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.])
        y = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.])
        # 定义两个掩码
        m1 = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
        m2 = [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1]
        # 使用自定义方法创建掩码数组
        xm = self.masked_array(x, mask=m1)
        ym = self.masked_array(y, mask=m2)
        # 创建一个填充值为 1.e+20 的新数组
        xf = np.where(m1, 1.e+20, x)
        # 设置 xm 的填充值为 1.e+20
        xm.set_fill_value(1.e+20)

        # 断言 xm 和 ym 的差异中任何一个被填充后不为零
        assert((xm-ym).filled(0).any())
        # 获取 x 的形状
        s = x.shape
        # 断言 xm 的大小等于其形状元素数的乘积
        assert(xm.size == reduce(lambda x, y:x*y, s))
        # 断言计算 xm 中未掩码元素的数量等于 m1 中 1 的数量
        assert(self.count(xm) == len(m1) - reduce(lambda x, y:x+y, m1))

        # 遍历不同形状并重置数组形状进行断言
        for s in [(4, 3), (6, 2)]:
            x.shape = s
            y.shape = s
            xm.shape = s
            ym.shape = s
            xf.shape = s
            # 再次断言计算 xm 中未掩码元素的数量等于 m1 中 1 的数量
            assert(self.count(xm) == len(m1) - reduce(lambda x, y:x+y, m1))

    @np.errstate(all='ignore')
    # 使用 NumPy 的错误状态管理器,忽略所有错误
    def test_2(self):
        """
        Tests conversions and indexing.

        """
        # 创建初始数组
        x1 = np.array([1, 2, 4, 3])
        # 使用自定义方法创建带有掩码的数组
        x2 = self.array(x1, mask=[1, 0, 0, 0])
        x3 = self.array(x1, mask=[0, 1, 0, 1])
        x4 = self.array(x1)
        # 测试转换为字符串,确保没有错误
        str(x2)
        repr(x2)
        # 索引测试
        assert type(x2[1]) is type(x1[1])
        assert x1[1] == x2[1]
        x1[2] = 9
        x2[2] = 9
        self.assert_array_equal(x1, x2)
        x1[1:3] = 99
        x2[1:3] = 99
        x2[1] = self.masked
        x2[1:3] = self.masked
        x2[:] = x1
        x2[1] = self.masked
        x3[:] = self.masked_array([1, 2, 3, 4], [0, 1, 1, 0])
        x4[:] = self.masked_array([1, 2, 3, 4], [0, 1, 1, 0])
        x1 = np.arange(5)*1.0
        # 使用自定义方法创建带有特定屏蔽值的数组
        x2 = self.masked_values(x1, 3.0)
        x1 = self.array([1, 'hello', 2, 3], object)
        x2 = np.array([1, 'hello', 2, 3], object)
        # 检查是否没有发生错误
        x1[1]
        x2[1]
        # 断言切片后的形状为空元组
        assert x1[1:1].shape == (0,)
        # 复制大小测试
        n = [0, 0, 1, 0, 0]
        m = self.make_mask(n)
        m2 = self.make_mask(m)
        # 断言 m 和 m2 是同一个对象
        assert(m is m2)
        m3 = self.make_mask(m, copy=1)
        # 断言 m 和 m3 不是同一个对象
        assert(m is not m3)

    @np.errstate(all='ignore')
    # 使用 NumPy 的错误状态管理器,忽略所有错误
    def test_3(self):
        """
        Tests resize/repeat

        """
        # 创建数组并将索引为 2 的元素设置为掩码
        x4 = self.arange(4)
        x4[2] = self.masked
        # 调整数组大小至 (8,)
        y4 = self.resize(x4, (8,))
        # 断言连接 x4 两次的结果等于 y4
        assert self.allequal(self.concatenate([x4, x4]), y4)
        # 断言 y4 的掩码为 [0, 0, 1, 0, 0, 0, 1, 0]
        assert self.allequal(self.getmask(y4), [0, 0, 1, 0, 0, 0, 1, 0])
        # 将 x4 按指定重复次数重复,并进行断言
        y5 = self.repeat(x4, (2, 2, 2, 2), axis=0)
        self.assert_array_equal(y5, [0, 0, 1, 1, 2, 2, 3, 3])
        y6 = self.repeat(x4, 2, axis=0)
        assert self.allequal(y5, y6)
        y7 = x4.repeat((2, 2, 2, 2), axis=0)
        assert self.allequal(y5, y7)
        y8 = x4.repeat(2, 0)
        assert self.allequal(y5, y8)
    # 定义一个测试方法,用于测试 take、transpose、inner、outer 函数的功能
    def test_4(self):
        """
        Test of take, transpose, inner, outer products.
        
        测试 take、transpose、inner、outer 函数的功能。
        """
        # 创建一个包含 24 个元素的数组 x,元素从 0 到 23
        x = self.arange(24)
        # 创建一个包含 24 个元素的数组 y,元素从 0 到 23
        y = np.arange(24)
        # 将 x 数组中索引为 5 的元素替换为 self.masked
        x[5:6] = self.masked
        # 将 x 数组重塑为形状为 (2, 3, 4) 的三维数组
        x = x.reshape(2, 3, 4)
        # 将 y 数组重塑为形状为 (2, 3, 4) 的三维数组
        y = y.reshape(2, 3, 4)
        
        # 断言 np.transpose(y, (2, 0, 1)) 与 self.transpose(x, (2, 0, 1)) 相等
        assert self.allequal(np.transpose(y, (2, 0, 1)), self.transpose(x, (2, 0, 1)))
        # 断言 np.take(y, (2, 0, 1), 1) 与 self.take(x, (2, 0, 1), 1) 相等
        assert self.allequal(np.take(y, (2, 0, 1), 1), self.take(x, (2, 0, 1), 1))
        # 断言 np.inner(self.filled(x, 0), self.filled(y, 0)) 与 self.inner(x, y) 相等
        assert self.allequal(np.inner(self.filled(x, 0), self.filled(y, 0)),
                            self.inner(x, y))
        # 断言 np.outer(self.filled(x, 0), self.filled(y, 0)) 与 self.outer(x, y) 相等
        assert self.allequal(np.outer(self.filled(x, 0), self.filled(y, 0)),
                            self.outer(x, y))
        
        # 创建一个包含字符串和整数的对象数组 y
        y = self.array(['abc', 1, 'def', 2, 3], object)
        # 将 y 数组中索引为 2 的元素替换为 self.masked
        y[2] = self.masked
        # 从 y 数组中取出索引为 [0, 3, 4] 的元素
        t = self.take(y, [0, 3, 4])
        # 断言取出的 t 数组的第一个元素等于 'abc'
        assert t[0] == 'abc'
        # 断言取出的 t 数组的第二个元素等于 2
        assert t[1] == 2
        # 断言取出的 t 数组的第三个元素等于 3
        assert t[2] == 3

    @np.errstate(all='ignore')
    # 在错误状态中运行测试方法,忽略所有错误
    def test_5(self):
        """
        Tests inplace w/ scalar
        
        测试原地操作与标量。
        """
        # 创建一个包含 10 个元素的数组 x,元素从 0 到 9
        x = self.arange(10)
        # 创建一个包含 10 个元素的数组 y,元素从 0 到 9
        y = self.arange(10)
        # 创建一个包含 10 个元素的数组 xm,并将索引为 2 的元素替换为 self.masked
        xm = self.arange(10)
        xm[2] = self.masked
        # 对 x 数组执行原地加法操作,每个元素加 1
        x += 1
        # 断言加法操作后的 x 数组与 y+1 数组相等
        assert self.allequal(x, y+1)
        # 对 xm 数组执行原地加法操作,每个元素加 1
        xm += 1
        # 断言加法操作后的 xm 数组与 y+1 数组相等
        assert self.allequal(xm, y+1)

        # 重复上述过程,分别测试减法、乘法、除法的原地操作
        x = self.arange(10)
        xm = self.arange(10)
        xm[2] = self.masked
        x -= 1
        assert self.allequal(x, y-1)
        xm -= 1
        assert self.allequal(xm, y-1)

        x = self.arange(10)*1.0
        xm = self.arange(10)*1.0
        xm[2] = self.masked
        x *= 2.0
        assert self.allequal(x, y*2)
        xm *= 2.0
        assert self.allequal(xm, y*2)

        x = self.arange(10)*2
        xm = self.arange(10)*2
        xm[2] = self.masked
        x /= 2
        assert self.allequal(x, y)
        xm /= 2
        assert self.allequal(xm, y)

        x = self.arange(10)*1.0
        xm = self.arange(10)*1.0
        xm[2] = self.masked
        x /= 2.0
        assert self.allequal(x, y/2.0)
        xm /= self.arange(10)
        self.assert_array_equal(xm, self.ones((10,)))

        x = self.arange(10).astype(np.float64)
        xm = self.arange(10)
        xm[2] = self.masked
        x += 1.
        assert self.allequal(x, y + 1.)
    # 定义测试函数 test_6,测试原地操作与数组的相关功能

    x = self.arange(10, dtype=np.float64)
    # 创建长度为 10 的浮点数数组 x

    y = self.arange(10)
    # 创建长度为 10 的整数数组 y

    xm = self.arange(10, dtype=np.float64)
    # 创建长度为 10 的浮点数数组 xm

    xm[2] = self.masked
    # 将 xm 数组的第 2 个位置设置为特定的掩码值 self.masked

    m = xm.mask
    # 获取数组 xm 的掩码

    a = self.arange(10, dtype=np.float64)
    # 创建长度为 10 的浮点数数组 a

    a[-1] = self.masked
    # 将数组 a 的最后一个位置设置为特定的掩码值 self.masked

    x += a
    # 将数组 x 与数组 a 原地相加

    xm += a
    # 将数组 xm 与数组 a 原地相加

    assert self.allequal(x, y+a)
    # 断言数组 x 应该与数组 y 加上数组 a 后相等

    assert self.allequal(xm, y+a)
    # 断言数组 xm 应该与数组 y 加上数组 a 后相等

    assert self.allequal(xm.mask, self.mask_or(m, a.mask))
    # 断言数组 xm 的掩码应该与数组 xm 的旧掩码 m 或上数组 a 的掩码后相等

    x = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 x

    xm = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 xm

    xm[2] = self.masked
    # 将 xm 数组的第 2 个位置设置为特定的掩码值 self.masked

    m = xm.mask
    # 获取数组 xm 的掩码

    a = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 a

    a[-1] = self.masked
    # 将数组 a 的最后一个位置设置为特定的掩码值 self.masked

    x -= a
    # 将数组 x 减去数组 a

    xm -= a
    # 将数组 xm 减去数组 a

    assert self.allequal(x, y-a)
    # 断言数组 x 应该与数组 y 减去数组 a 后相等

    assert self.allequal(xm, y-a)
    # 断言数组 xm 应该与数组 y 减去数组 a 后相等

    assert self.allequal(xm.mask, self.mask_or(m, a.mask))
    # 断言数组 xm 的掩码应该与数组 xm 的旧掩码 m 或上数组 a 的掩码后相等

    x = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 x

    xm = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 xm

    xm[2] = self.masked
    # 将 xm 数组的第 2 个位置设置为特定的掩码值 self.masked

    m = xm.mask
    # 获取数组 xm 的掩码

    a = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 a

    a[-1] = self.masked
    # 将数组 a 的最后一个位置设置为特定的掩码值 self.masked

    x *= a
    # 将数组 x 与数组 a 原地相乘

    xm *= a
    # 将数组 xm 与数组 a 原地相乘

    assert self.allequal(x, y*a)
    # 断言数组 x 应该与数组 y 乘以数组 a 后相等

    assert self.allequal(xm, y*a)
    # 断言数组 xm 应该与数组 y 乘以数组 a 后相等

    assert self.allequal(xm.mask, self.mask_or(m, a.mask))
    # 断言数组 xm 的掩码应该与数组 xm 的旧掩码 m 或上数组 a 的掩码后相等

    x = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 x

    xm = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 xm

    xm[2] = self.masked
    # 将 xm 数组的第 2 个位置设置为特定的掩码值 self.masked

    m = xm.mask
    # 获取数组 xm 的掩码

    a = self.arange(10, dtype=np.float64)
    # 重新创建长度为 10 的浮点数数组 a

    a[-1] = self.masked
    # 将数组 a 的最后一个位置设置为特定的掩码值 self.masked

    x /= a
    # 将数组 x 除以数组 a

    xm /= a
    # 将数组 xm 除以数组 a
# 循环遍历定义的一组数学函数名称列表
for f in [
             'sin', 'cos', 'tan',
             'arcsin', 'arccos', 'arctan',
             'sinh', 'cosh', 'tanh',
             'arcsinh',
             'arccosh',
             'arctanh',
             'absolute', 'fabs', 'negative',
             # 'nonzero', 'around',
             'floor', 'ceil',
             # 'sometrue', 'alltrue',
             'logical_not',
             'add', 'subtract', 'multiply',
             'divide', 'true_divide', 'floor_divide',
             'remainder', 'fmod', 'hypot', 'arctan2',
             'equal', 'not_equal', 'less_equal', 'greater_equal',
             'less', 'greater',
             'logical_and', 'logical_or', 'logical_xor',
         ]:
    try:
        # 尝试从 self.umath 中获取对应名称的函数对象
        uf = getattr(self.umath, f)
    except AttributeError:
        # 如果在 self.umath 中找不到,则从 fromnumeric 中获取对应名称的函数对象
        uf = getattr(fromnumeric, f)
    # 从 self.module 中获取对应名称的函数对象
    mf = getattr(self.module, f)
    # 从参数字典 d 中获取前 uf.nin 个参数作为函数调用的参数
    args = d[:uf.nin]
    # 调用 uf 函数并存储结果
    ur = uf(*args)
    # 调用 mf 函数并存储结果
    mr = mf(*args)
    # 使用 self.assert_array_equal 方法比较 ur 和 mr 对象的填充后值是否相等,并打印出错信息 f
    self.assert_array_equal(ur.filled(0), mr.filled(0), f)
    # 使用 self.assert_array_equal 方法比较 ur 和 mr 对象的掩码是否相等
    self.assert_array_equal(ur._mask, mr._mask)

# 在 numpy 中忽略所有错误状态
@np.errstate(all='ignore')
    # 定义一个测试方法,用于测试average函数的不同用例
    def test_99(self):
        # 创建一个带有部分掩码的数组ott,测试average函数在axis=0时的平均值
        ott = self.array([0., 1., 2., 3.], mask=[1, 0, 0, 0])
        self.assert_array_equal(2.0, self.average(ott, axis=0))
        # 测试带权重的average函数,验证平均值计算是否正确
        self.assert_array_equal(2.0, self.average(ott, weights=[1., 1., 2., 1.]))
        # 测试返回权重的average函数,确保返回的结果和权重值正确
        result, wts = self.average(ott, weights=[1., 1., 2., 1.], returned=1)
        self.assert_array_equal(2.0, result)
        assert(wts == 4.0)
        # 将ott数组全部置为masked,验证average函数在axis=0时的返回值是否正确为masked
        ott[:] = self.masked
        assert(self.average(ott, axis=0) is self.masked)
        # 将ott数组重新定义为未masked的数组,并reshape为2x2的矩阵
        ott = self.array([0., 1., 2., 3.], mask=[1, 0, 0, 0])
        ott = ott.reshape(2, 2)
        # 将ott的第二列置为masked,测试average函数在axis=0时的平均值计算
        ott[:, 1] = self.masked
        self.assert_array_equal(self.average(ott, axis=0), [2.0, 0.0])
        # 验证average函数在axis=1时,第一行的返回值是否正确为masked
        assert(self.average(ott, axis=1)[0] is self.masked)
        # 再次验证average函数在axis=0时的平均值计算是否正确
        self.assert_array_equal([2., 0.], self.average(ott, axis=0))
        # 测试返回权重的average函数在axis=0时,确保返回的权重值正确
        result, wts = self.average(ott, axis=0, returned=1)
        self.assert_array_equal(wts, [1., 0.])
        # 定义权重数组w1和w2,并创建一个包含0到5的数组x
        w1 = [0, 1, 1, 1, 1, 0]
        w2 = [[0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 0, 1]]
        x = self.arange(6)
        # 验证average函数在axis=0时,计算数组x的平均值是否正确
        self.assert_array_equal(self.average(x, axis=0), 2.5)
        # 验证带权重的average函数在axis=0时,计算数组x的平均值是否正确
        self.assert_array_equal(self.average(x, axis=0, weights=w1), 2.5)
        # 创建一个包含两行的数组y,并验证average函数在None条件下的计算结果是否正确
        y = self.array([self.arange(6), 2.0*self.arange(6)])
        self.assert_array_equal(self.average(y, None), np.add.reduce(np.arange(6))*3./12.)
        # 验证average函数在axis=0时,计算数组y的平均值是否正确
        self.assert_array_equal(self.average(y, axis=0), np.arange(6) * 3./2.)
        # 验证average函数在axis=1时,计算数组y的平均值是否正确
        self.assert_array_equal(self.average(y, axis=1), [self.average(x, axis=0), self.average(x, axis=0) * 2.0])
        # 验证带权重的average函数在None条件下,计算数组y的平均值是否正确
        self.assert_array_equal(self.average(y, None, weights=w2), 20./6.)
        # 验证带权重的average函数在axis=0时,计算数组y的平均值是否正确
        self.assert_array_equal(self.average(y, axis=0, weights=w2), [0., 1., 2., 3., 4., 10.])
        # 定义一些掩码数组m1到m5,并验证average函数在对应掩码条件下的平均值计算结果是否正确
        m1 = self.zeros(6)
        m2 = [0, 0, 1, 1, 0, 0]
        m3 = [[0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0]]
        m4 = self.ones(6)
        m5 = [0, 1, 1, 1, 1, 1]
        self.assert_array_equal(self.average(self.masked_array(x, m1), axis=0), 2.5)
        self.assert_array_equal(self.average(self.masked_array(x, m2), axis=0), 2.5)
        self.assert_array_equal(self.average(self.masked_array(x, m5), axis=0), 0.0)
        self.assert_array_equal(self.count(self.average(self.masked_array(x, m4), axis=0)), 0)
        # 创建一个包含掩码数组m3的数组z,并验证average函数在不同axis条件下的计算结果是否正确
        z = self.masked_array(y, m3)
        self.assert_array_equal(self.average(z, None), 20./6.)
        self.assert_array_equal(self.average(z, axis=0), [0., 1., 99., 99., 4.0, 7.5])
        self.assert_array_equal(self.average(z, axis=1), [2.5, 5.0])
        # 验证带权重的average函数在axis=0时,计算数组z的平均值是否正确
        self.assert_array_equal(self.average(z, axis=0, weights=w2), [0., 1., 99., 99., 4.0, 10.0])

    # 定义一个测试方法,用于测试在忽略所有错误情况下,数组操作的功能
    @np.errstate(all='ignore')
    def test_A(self):
        # 创建一个包含掩码值的数组x,并对其中一个元素应用masked操作
        x = self.arange(24)
        x[5:6] = self.masked
        # 将数组x重新reshape为2x3x4的三维数组
        x = x.reshape(2, 3, 4)
if __name__ == '__main__':
    # 如果当前脚本作为主程序执行
    setup_base = ("from __main__ import ModuleTester \n"
                  "import numpy\n"
                  "tester = ModuleTester(module)\n")
    # 设置基础的导入语句和模块测试器的初始化
    setup_cur = "import numpy.ma.core as module\n" + setup_base
    # 设置当前的导入语句,包括numpy.ma.core作为module,并继承基础设置

    (nrepeat, nloop) = (10, 10)
    # 定义重复执行和循环次数的元组

    for i in range(1, 8):
        # 循环执行以下操作,i从1到7
        func = 'tester.test_%i()' % i
        # 生成当前测试函数的字符串表示形式,例如'tester.test_1()'
        cur = timeit.Timer(func, setup_cur).repeat(nrepeat, nloop*10)
        # 使用timeit.Timer来测量func函数的执行时间,重复nrepeat次,每次循环执行nloop*10次
        cur = np.sort(cur)
        # 对测量结果进行排序
        print("#%i" % i + 50*'.')
        # 打印当前测试编号,以及一行分隔符
        print(eval("ModuleTester.test_%i.__doc__" % i))
        # 打印当前测试函数的文档字符串
        print(f'core_current : {cur[0]:.3f} - {cur[1]:.3f}')
        # 打印测量结果的最小值和最大值,保留三位小数精度

.\numpy\numpy\ma\__init__.py

"""
=============
Masked Arrays
=============

Arrays sometimes contain invalid or missing data.  When doing operations
on such arrays, we wish to suppress invalid values, which is the purpose masked
arrays fulfill (an example of typical use is given below).

For example, examine the following array:

>>> x = np.array([2, 1, 3, np.nan, 5, 2, 3, np.nan])

When we try to calculate the mean of the data, the result is undetermined:

>>> np.mean(x)
nan

The mean is calculated using roughly ``np.sum(x)/len(x)``, but since
any number added to ``NaN`` [1]_ produces ``NaN``, this doesn't work.  Enter
masked arrays:

>>> m = np.ma.masked_array(x, np.isnan(x))
>>> m
masked_array(data=[2.0, 1.0, 3.0, --, 5.0, 2.0, 3.0, --],
             mask=[False, False, False, True, False, False, False, True],
      fill_value=1e+20)

Here, we construct a masked array that suppresses all ``NaN`` values.  We
may now proceed to calculate the mean of the other values:

>>> np.mean(m)
2.6666666666666665

.. [1] Not-a-Number, a floating point value that is the result of an
       invalid operation.

.. moduleauthor:: Pierre Gerard-Marchant
.. moduleauthor:: Jarrod Millman

"""

# 导入核心模块和其所有内容
from . import core
from .core import *

# 导入额外模块和其所有内容
from . import extras
from .extras import *

# 将核心模块和额外模块的公开接口添加到当前模块的公开接口中
__all__ = ['core', 'extras']
__all__ += core.__all__
__all__ += extras.__all__

# 导入 numpy 的 PytestTester 类并创建一个测试对象 test
from numpy._pytesttester import PytestTester
test = PytestTester(__name__)
# 删除 PytestTester 类的引用,以避免被直接访问
del PytestTester

.\numpy\numpy\ma\__init__.pyi

# 导入 numpy._pytesttester 模块中的 PytestTester 类
from numpy._pytesttester import PytestTester

# 导入 numpy.ma 模块中的 extras 子模块
from numpy.ma import extras as extras

# 导入 numpy.ma.core 模块中的以下类和函数
from numpy.ma.core import (
    # 定义异常类 MAError 别名为 MAError
    MAError as MAError,
    # 定义异常类 MaskError 别名为 MaskError
    MaskError as MaskError,
    # 定义 MaskType 类别名为 MaskType
    MaskType as MaskType,
    # 定义 MaskedArray 类别名为 MaskedArray
    MaskedArray as MaskedArray,
    # 导入函数 abs 别名为 abs
    abs as abs,
    # 导入函数 absolute 别名为 absolute
    absolute as absolute,
    # 导入函数 add 别名为 add
    add as add,
    # 导入函数 all 别名为 all
    all as all,
    # 导入函数 allclose 别名为 allclose
    allclose as allclose,
    # 导入函数 allequal 别名为 allequal
    allequal as allequal,
    # 导入函数 alltrue 别名为 alltrue
    alltrue as alltrue,
    # 导入函数 amax 别名为 amax
    amax as amax,
    # 导入函数 amin 别名为 amin
    amin as amin,
    # 导入函数 angle 别名为 angle
    angle as angle,
    # 导入函数 anom 别名为 anom
    anom as anom,
    # 导入函数 anomalies 别名为 anomalies
    anomalies as anomalies,
    # 导入函数 any 别名为 any
    any as any,
    # 导入函数 append 别名为 append
    append as append,
    # 导入函数 arange 别名为 arange
    arange as arange,
    # 导入函数 arccos 别名为 arccos
    arccos as arccos,
    # 导入函数 arccosh 别名为 arccosh
    arccosh as arccosh,
    # 导入函数 arcsin 别名为 arcsin
    arcsin as arcsin,
    # 导入函数 arcsinh 别名为 arcsinh
    arcsinh as arcsinh,
    # 导入函数 arctan 别名为 arctan
    arctan as arctan,
    # 导入函数 arctan2 别名为 arctan2
    arctan2 as arctan2,
    # 导入函数 arctanh 别名为 arctanh
    arctanh as arctanh,
    # 导入函数 argmax 别名为 argmax
    argmax as argmax,
    # 导入函数 argmin 别名为 argmin
    argmin as argmin,
    # 导入函数 argsort 别名为 argsort
    argsort as argsort,
    # 导入函数 around 别名为 around
    around as around,
    # 导入函数 array 别名为 array
    array as array,
    # 导入函数 asanyarray 别名为 asanyarray
    asanyarray as asanyarray,
    # 导入函数 asarray 别名为 asarray
    asarray as asarray,
    # 导入函数 bitwise_and 别名为 bitwise_and
    bitwise_and as bitwise_and,
    # 导入函数 bitwise_or 别名为 bitwise_or
    bitwise_or as bitwise_or,
    # 导入函数 bitwise_xor 别名为 bitwise_xor
    bitwise_xor as bitwise_xor,
    # 导入 bool 类型别名为 bool
    bool as bool,
    # 导入函数 ceil 别名为 ceil
    ceil as ceil,
    # 导入函数 choose 别名为 choose
    choose as choose,
    # 导入函数 clip 别名为 clip
    clip as clip,
    # 导入函数 common_fill_value 别名为 common_fill_value
    common_fill_value as common_fill_value,
    # 导入函数 compress 别名为 compress
    compress as compress,
    # 导入函数 compressed 别名为 compressed
    compressed as compressed,
    # 导入函数 concatenate 别名为 concatenate
    concatenate as concatenate,
    # 导入函数 conjugate 别名为 conjugate
    conjugate as conjugate,
    # 导入函数 convolve 别名为 convolve
    convolve as convolve,
    # 导入函数 copy 别名为 copy
    copy as copy,
    # 导入函数 correlate 别名为 correlate
    correlate as correlate,
    # 导入函数 cos 别名为 cos
    cos as cos,
    # 导入函数 cosh 别名为 cosh
    cosh as cosh,
    # 导入函数 count 别名为 count
    count as count,
    # 导入函数 cumprod 别名为 cumprod
    cumprod as cumprod,
    # 导入函数 cumsum 别名为 cumsum
    cumsum as cumsum,
    # 导入函数 default_fill_value 别名为 default_fill_value
    default_fill_value as default_fill_value,
    # 导入函数 diag 别名为 diag
    diag as diag,
    # 导入函数 diagonal 别名为 diagonal
    diagonal as diagonal,
    # 导入函数 diff 别名为 diff
    diff as diff,
    # 导入函数 divide 别名为 divide
    divide as divide,
    # 导入函数 empty 别名为 empty
    empty as empty,
    # 导入函数 empty_like 别名为 empty_like
    empty_like as empty_like,
    # 导入函数 equal 别名为 equal
    equal as equal,
    # 导入函数 exp 别名为 exp
    exp as exp,
    # 导入函数 expand_dims 别名为 expand_dims
    expand_dims as expand_dims,
    # 导入函数 fabs 别名为 fabs
    fabs as fabs,
    # 导入函数 filled 别名为 filled
    filled as filled,
    # 导入函数 fix_invalid 别名为 fix_invalid
    fix_invalid as fix_invalid,
    # 导入函数 flatten_mask 别名为 flatten_mask
    flatten_mask as flatten_mask,
    # 导入函数 flatten_structured_array 别名为 flatten_structured_array
    flatten_structured_array as flatten_structured_array,
    # 导入函数 floor 别名为 floor
    floor as floor,
    # 导入函数 floor_divide 别名为 floor_divide
    floor_divide as floor_divide,
    # 导入函数 fmod 别名为 fmod
    fmod as fmod,
    # 导入函数 frombuffer 别名为 frombuffer
    frombuffer as frombuffer,
    # 导入函数 fromflex 别名为 fromflex
    fromflex as fromflex,
    # 导入函数 fromfunction 别名为 fromfunction
    fromfunction as fromfunction,
    # 导入函数 getdata 别名为 getdata
    getdata as getdata,
    # 导入函数 getmask 别名为 getmask
    getmask as getmask,
    # 导入函数 getmaskarray 别名为 getmaskarray
    getmaskarray as getmaskarray,
    # 导入函数 greater 别名为 greater
    greater as greater,
    # 导入函数 greater_equal 别名为 greater_equal
    greater_equal as greater_equal,
    # 导入函数 harden_mask 别名为 harden_mask
    harden_mask as harden_mask,
    # 导入函数 hypot 别名为 hypot
    hypot as hypot,
    # 导入函数 identity 别名为 identity
    identity as identity,
    # 导入函数 ids 别名为 ids
    ids as ids,
    # 导入函数 indices 别名为 indices
    indices as indices,
    # 导入函数 inner 别名为 inner
    inner as inner,
    # 导入函数 innerproduct 别名为 innerproduct
    innerproduct as innerproduct,
    # 导入函数 isMA 别名为 isMA
    isMA as isMA,
    # 导入函数 isMaskedArray 别名为 isMaskedArray
    isMaskedArray as isMaskedArray,
    # 导入函数 is_mask 别名为 is_mask
    is_mask as is_mask,
    # 导入函数 is_masked 别名为 is_masked
    is_masked as is_masked,
    # 导入函数 isarray 别名为 isarray
    isarray as isarray,
    # 导入函数 left_shift 别名为 left_shift
    left_shift as left_shift,
    # 导入函数 less 别名为 less
    less as
    # 导入所需的函数和方法,用于处理掩码数组的操作和数学运算
    masked_invalid as masked_invalid,        # 导入函数 masked_invalid,用于处理无效掩码
    masked_less as masked_less,              # 导入函数 masked_less,用于处理小于比较掩码
    masked_less_equal as masked_less_equal,  # 导入函数 masked_less_equal,用于处理小于等于比较掩码
    masked_not_equal as masked_not_equal,    # 导入函数 masked_not_equal,用于处理不等于比较掩码
    masked_object as masked_object,          # 导入函数 masked_object,用于处理对象掩码
    masked_outside as masked_outside,        # 导入函数 masked_outside,用于处理外部掩码
    masked_print_option as masked_print_option,  # 导入函数 masked_print_option,用于掩码打印选项
    masked_singleton as masked_singleton,    # 导入函数 masked_singleton,用于处理单例掩码
    masked_values as masked_values,          # 导入函数 masked_values,用于处理数值掩码
    masked_where as masked_where,            # 导入函数 masked_where,用于条件掩码
    max as max,                              # 导入 max 函数,用于求最大值
    maximum as maximum,                      # 导入 maximum 函数,用于求最大值
    maximum_fill_value as maximum_fill_value,  # 导入 maximum_fill_value 函数,用于最大填充值
    mean as mean,                            # 导入 mean 函数,用于求均值
    min as min,                              # 导入 min 函数,用于求最小值
    minimum as minimum,                      # 导入 minimum 函数,用于求最小值
    minimum_fill_value as minimum_fill_value,  # 导入 minimum_fill_value 函数,用于最小填充值
    mod as mod,                              # 导入 mod 函数,用于求余数
    multiply as multiply,                    # 导入 multiply 函数,用于求乘积
    mvoid as mvoid,                          # 导入 mvoid 函数,用于处理虚类型
    ndim as ndim,                            # 导入 ndim 函数,用于返回数组的维度数
    negative as negative,                    # 导入 negative 函数,用于求负数
    nomask as nomask,                        # 导入 nomask 函数,用于不使用掩码
    nonzero as nonzero,                      # 导入 nonzero 函数,用于返回非零元素的索引
    not_equal as not_equal,                  # 导入 not_equal 函数,用于比较不等于
    ones as ones,                            # 导入 ones 函数,用于创建全为1的数组
    outer as outer,                          # 导入 outer 函数,用于外积计算
    outerproduct as outerproduct,            # 导入 outerproduct 函数,用于外积计算
    power as power,                          # 导入 power 函数,用于幂运算
    prod as prod,                            # 导入 prod 函数,用于计算数组元素的乘积
    product as product,                      # 导入 product 函数,用于计算数组元素的乘积
    ptp as ptp,                              # 导入 ptp 函数,用于计算数组的峰值到峰值范围
    put as put,                              # 导入 put 函数,用于按照索引赋值
    putmask as putmask,                      # 导入 putmask 函数,用于按照掩码条件赋值
    ravel as ravel,                          # 导入 ravel 函数,用于将多维数组展平为一维数组
    remainder as remainder,                  # 导入 remainder 函数,用于求余数
    repeat as repeat,                        # 导入 repeat 函数,用于重复数组元素
    reshape as reshape,                      # 导入 reshape 函数,用于改变数组形状
    resize as resize,                        # 导入 resize 函数,用于改变数组大小
    right_shift as right_shift,              # 导入 right_shift 函数,用于右移位运算
    round as round,                          # 导入 round 函数,用于四舍五入
    set_fill_value as set_fill_value,        # 导入 set_fill_value 函数,用于设置填充值
    shape as shape,                          # 导入 shape 函数,用于返回数组的形状
    sin as sin,                              # 导入 sin 函数,用于求正弦值
    sinh as sinh,                            # 导入 sinh 函数,用于求双曲正弦值
    size as size,                            # 导入 size 函数,用于返回数组元素的个数
    soften_mask as soften_mask,              # 导入 soften_mask 函数,用于软化掩码
    sometrue as sometrue,                    # 导入 sometrue 函数,用于判断是否有真值
    sort as sort,                            # 导入 sort 函数,用于数组排序
    sqrt as sqrt,                            # 导入 sqrt 函数,用于求平方根
    squeeze as squeeze,                      # 导入 squeeze 函数,用于去除维度为1的轴
    std as std,                              # 导入 std 函数,用于求标准差
    subtract as subtract,                    # 导入 subtract 函数,用于求差值
    sum as sum,                              # 导入 sum 函数,用于求和
    swapaxes as swapaxes,                    # 导入 swapaxes 函数,用于交换数组的轴
    take as take,                            # 导入 take 函数,用于按索引获取数组元素
    tan as tan,                              # 导入 tan 函数,用于求正切值
    tanh as tanh,                            # 导入 tanh 函数,用于求双曲正切值
    trace as trace,                          # 导入 trace 函数,用于计算对角线元素的和
    transpose as transpose,                  # 导入 transpose 函数,用于矩阵转置
    true_divide as true_divide,              # 导入 true_divide 函数,用于真实除法
    var as var,                              # 导入 var 函数,用于求方差
    where as where,                          # 导入 where 函数,用于条件选择
    zeros as zeros,                          # 导入 zeros 函数,用于创建全为0的数组
# 导入 numpy.ma.extras 模块中的多个函数,并使用简化的别名
from numpy.ma.extras import (
    apply_along_axis as apply_along_axis,           # 别名 apply_along_axis,沿指定轴应用函数
    apply_over_axes as apply_over_axes,             # 别名 apply_over_axes,沿指定一组轴应用函数
    atleast_1d as atleast_1d,                       # 别名 atleast_1d,将输入至少转换为 1 维数组
    atleast_2d as atleast_2d,                       # 别名 atleast_2d,将输入至少转换为 2 维数组
    atleast_3d as atleast_3d,                       # 别名 atleast_3d,将输入至少转换为 3 维数组
    average as average,                             # 别名 average,计算数组的加权平均值
    clump_masked as clump_masked,                   # 别名 clump_masked,将掩码数组的相邻条目组合成序列
    clump_unmasked as clump_unmasked,               # 别名 clump_unmasked,将未掩码数组的相邻条目组合成序列
    column_stack as column_stack,                   # 别名 column_stack,按列堆叠序列或数组
    compress_cols as compress_cols,                 # 别名 compress_cols,压缩列中的掩码数组
    compress_nd as compress_nd,                     # 别名 compress_nd,压缩多维数组的掩码数组
    compress_rowcols as compress_rowcols,           # 别名 compress_rowcols,压缩行列中的掩码数组
    compress_rows as compress_rows,                 # 别名 compress_rows,压缩行中的掩码数组
    count_masked as count_masked,                   # 别名 count_masked,计算数组中掩码条目的数量
    corrcoef as corrcoef,                           # 别名 corrcoef,计算相关系数矩阵
    cov as cov,                                     # 别名 cov,计算协方差矩阵
    diagflat as diagflat,                           # 别名 diagflat,创建对角扁平数组
    dot as dot,                                     # 别名 dot,计算两个数组的点积
    dstack as dstack,                               # 别名 dstack,按深度堆叠序列或数组
    ediff1d as ediff1d,                             # 别名 ediff1d,计算 1 维数组的首差值
    flatnotmasked_contiguous as flatnotmasked_contiguous,  # 别名 flatnotmasked_contiguous,返回连续未掩码条目的迭代器
    flatnotmasked_edges as flatnotmasked_edges,     # 别名 flatnotmasked_edges,返回边界未掩码条目的迭代器
    hsplit as hsplit,                               # 别名 hsplit,水平分割数组成子数组
    hstack as hstack,                               # 别名 hstack,按水平堆叠序列或数组
    isin as isin,                                   # 别名 isin,测试数组的成员资格
    in1d as in1d,                                   # 别名 in1d,测试数组的成员资格,返回布尔数组
    intersect1d as intersect1d,                     # 别名 intersect1d,计算两个数组的交集
    mask_cols as mask_cols,                         # 别名 mask_cols,返回列中的掩码数组
    mask_rowcols as mask_rowcols,                   # 别名 mask_rowcols,返回行列中的掩码数组
    mask_rows as mask_rows,                         # 别名 mask_rows,返回行中的掩码数组
    masked_all as masked_all,                       # 别名 masked_all,创建所有掩码数组
    masked_all_like as masked_all_like,             # 别名 masked_all_like,创建与输入形状相同的所有掩码数组
    median as median,                               # 别名 median,计算数组的中位数
    mr_ as mr_,                                     # 别名 mr_,返回平滑移动均值的序列
    ndenumerate as ndenumerate,                     # 别名 ndenumerate,返回多维数组的索引和值的迭代器
    notmasked_contiguous as notmasked_contiguous,   # 别名 notmasked_contiguous,返回连续未掩码条目的迭代器
    notmasked_edges as notmasked_edges,             # 别名 notmasked_edges,返回边界未掩码条目的迭代器
    polyfit as polyfit,                             # 别名 polyfit,计算多项式拟合
    row_stack as row_stack,                         # 别名 row_stack,按行堆叠序列或数组
    setdiff1d as setdiff1d,                         # 别名 setdiff1d,计算两个数组的差集
    setxor1d as setxor1d,                           # 别名 setxor1d,计算两个数组的异或集
    stack as stack,                                 # 别名 stack,按堆叠序列或数组
    unique as unique,                               # 别名 unique,查找数组的唯一元素
    union1d as union1d,                             # 别名 union1d,计算两个数组的并集
    vander as vander,                               # 别名 vander,生成范德蒙矩阵
    vstack as vstack                                # 别名 vstack,按垂直堆叠序列或数组
)

__all__: list[str]   # 定义一个列表,包含模块中应导出的所有公共名称
test: PytestTester    # 定义一个变量 test,其类型为 PytestTester,可能用于测试相关功能

.\numpy\numpy\matlib.py

import warnings

# 在导入 numpy.matlib 的过程中,如果使用 matrix 类别会出现弃用警告
# 此警告于 numpy 1.19.0 版本添加,并且在此处设置 stacklevel=2 以准确显示警告位置
warnings.warn("Importing from numpy.matlib is deprecated since 1.19.0. "
              "The matrix subclass is not the recommended way to represent "
              "matrices or deal with linear algebra (see "
              "https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). "
              "Please adjust your code to use regular ndarray. ",
              PendingDeprecationWarning, stacklevel=2)

import numpy as np
from numpy.matrixlib.defmatrix import matrix, asmatrix

# Matlib.py 文件包含了 numpy 命名空间的所有函数,但做了一些替换
# 参见 doc/source/reference/routines.matlib.rst 了解详细信息
# 此处使用 * 从 numpy 中复制命名空间,包括了所有函数和对象
from numpy import *  # noqa: F403

__version__ = np.__version__

# 复制 numpy 命名空间到当前模块的 __all__ 中
__all__ = np.__all__[:]  # copy numpy namespace
__all__ += ['rand', 'randn', 'repmat']

def empty(shape, dtype=None, order='C'):
    """Return a new matrix of given shape and type, without initializing entries.

    Parameters
    ----------
    shape : int or tuple of int
        Shape of the empty matrix.
    dtype : data-type, optional
        Desired output data-type.
    order : {'C', 'F'}, optional
        Whether to store multi-dimensional data in row-major
        (C-style) or column-major (Fortran-style) order in
        memory.

    See Also
    --------
    numpy.empty : Equivalent array function.
    matlib.zeros : Return a matrix of zeros.
    matlib.ones : Return a matrix of ones.

    Notes
    -----
    Unlike other matrix creation functions (e.g. `matlib.zeros`,
    `matlib.ones`), `matlib.empty` does not initialize the values of the
    matrix, and may therefore be marginally faster. However, the values
    stored in the newly allocated matrix are arbitrary. For reproducible
    behavior, be sure to set each element of the matrix before reading.

    Examples
    --------
    >>> import numpy.matlib
    >>> np.matlib.empty((2, 2))    # filled with random data
    matrix([[  6.76425276e-320,   9.79033856e-307], # random
            [  7.39337286e-309,   3.22135945e-309]])
    >>> np.matlib.empty((2, 2), dtype=int)
    matrix([[ 6600475,        0], # random
            [ 6586976, 22740995]])

    """
    # 创建一个新的矩阵对象,但不初始化条目的值
    return ndarray.__new__(matrix, shape, dtype, order=order)

def ones(shape, dtype=None, order='C'):
    """
    Matrix of ones.

    Return a matrix of given shape and type, filled with ones.

    Parameters
    ----------
    shape : {sequence of ints, int}
        Shape of the matrix
    dtype : data-type, optional
        The desired data-type for the matrix, default is np.float64.
    order : {'C', 'F'}, optional
        Whether to store matrix in C- or Fortran-contiguous order,
        default is 'C'.

    Returns
    -------
    out : matrix
        Matrix of ones of given shape, dtype, and order.

    See Also
    --------
    ones : Array of ones.

    """
    # 返回一个给定形状和类型的矩阵,填充为全部为 1
    return np.ones(shape, dtype=dtype, order=order)
    # 使用 matlib 模块中的 zeros 函数创建一个零矩阵。
    # 
    # Notes
    # -----
    # 如果 `shape` 的长度为一,即 ``(N,)``,或者是一个标量 `N`,则 `out` 将变成一个形状为 ``(1,N)`` 的单行矩阵。
    # 
    # Examples
    # --------
    # >>> np.matlib.ones((2,3))
    # matrix([[1.,  1.,  1.],
    #         [1.,  1.,  1.]])
    # 
    # >>> np.matlib.ones(2)
    # matrix([[1.,  1.]])
    # 
    def zeros(shape, dtype=None, order='C'):
        """
        a = ndarray.__new__(matrix, shape, dtype, order=order)
        使用给定的 shape、dtype 和 order 创建一个新的 matrix 对象 a。
        """
        a = ndarray.__new__(matrix, shape, dtype, order=order)
        # 用值 1 填充矩阵 a
        a.fill(1)
        return a
# 返回一个给定形状和类型的零矩阵。

def zeros(shape, dtype=None, order='C'):
    # 创建一个新的矩阵对象,继承自 ndarray 类型的 matrix,并初始化为零矩阵
    a = ndarray.__new__(matrix, shape, dtype, order=order)
    # 将矩阵中的所有元素填充为零
    a.fill(0)
    return a

# 返回给定大小的单位矩阵。

def identity(n,dtype=None):
    # 创建一个长度为 n 的列表,第一个元素为 1,其余为 0,并指定数据类型为 dtype
    a = array([1]+n*[0], dtype=dtype)
    # 创建一个 n x n 的空矩阵,并将其扁平化后赋值为列表 a,形成单位矩阵
    b = empty((n, n), dtype=dtype)
    b.flat = a
    return b

# 返回一个主对角线上元素为 1 其余为零的矩阵。

def eye(n,M=None, k=0, dtype=float, order='C'):
    # 创建一个 n x M 的零矩阵,默认情况下 M 等于 n
    I = zeros((n, M if M else n), dtype=dtype, order=order)
    # 根据参数 k,在矩阵中设置对应对角线上的元素为 1
    if k >= 0:
        I.flat[k::I.shape[1]+1] = 1
    else:
        I.flat[-k*I.shape[1]::I.shape[1]-1] = 1
    return I
    # 创建一个 n x M 的单位矩阵,其中从主对角线偏移 k 个位置,并指定数据类型为 float
    >>> np.matlib.eye(3, k=1, dtype=float)
    matrix([[0.,  1.,  0.],
            [0.,  0.,  1.],
            [0.,  0.,  0.]])
    """
    返回一个 n x M 的单位矩阵的 numpy 矩阵表示,其中对角线向上偏移 k 个位置。
def repmat(a, m, n):
    """
    Repeat a 0-D to 2-D array or matrix MxN times.

    Parameters
    ----------
    a : array_like
        The array or matrix to be repeated.
    m : int
        Number of times the input array `a` is repeated along the first dimension.
    n : int
        Number of times the input array `a` is repeated along the second dimension, if `a` is 2-D.

    Returns
    -------
    out : ndarray
        The tiled output array.

    See Also
    --------
    tile, numpy.matlib.repmat

    Notes
    -----
    If `a` is 0-D or 1-D, the result will be a 1-D array repeating `a` `m` times.
    If `a` is 2-D, the result will be a 2-D array repeating `a` `m` times along the first axis and `n` times along the second axis.

    Examples
    --------
    >>> np.matlib.repmat(np.array([[1, 2], [3, 4]]), 2, 3)
    matrix([[1, 2, 1, 2, 1, 2],
            [3, 4, 3, 4, 3, 4],
            [1, 2, 1, 2, 1, 2],
            [3, 4, 3, 4, 3, 4]])

    >>> np.matlib.repmat(np.array([1, 2]), 3, 2)
    matrix([[1, 2],
            [1, 2],
            [1, 2]])

    """
    # 使用 numpy 的 tile 函数实现重复数组 a 的操作
    return np.tile(np.asarray(a), (m, n))
    # 将输入参数 `a` 转换为多维数组
    a = asanyarray(a)
    
    # 获取数组 `a` 的维度
    ndim = a.ndim
    
    # 根据数组的维度确定原始行数和列数
    if ndim == 0:
        origrows, origcols = (1, 1)  # 对于零维数组,原始行数和列数均为1
    elif ndim == 1:
        origrows, origcols = (1, a.shape[0])  # 对于一维数组,原始行数为1,列数为数组长度
    else:
        origrows, origcols = a.shape  # 对于高维数组,原始行数和列数即为数组的形状
    
    # 计算重复后的总行数和总列数
    rows = origrows * m
    cols = origcols * n
    
    # 将数组 `a` 展平为一维,并按指定的行数 `m` 重复堆叠,然后按原始列数重新整形
    # 再按指定的列数 `n` 重复堆叠,形成最终的重复数组
    c = a.reshape(1, a.size).repeat(m, 0).reshape(rows, origcols).repeat(n, 0)
    
    # 返回重复后的数组,重新整形为指定的总行数和总列数
    return c.reshape(rows, cols)

.\numpy\numpy\matrixlib\defmatrix.py

__all__ = ['matrix', 'bmat', 'asmatrix']

# 导入所需模块和库
import sys
import warnings
import ast

# 从模块中导入函数和类
from .._utils import set_module

# 导入核心数值计算模块及其函数
import numpy._core.numeric as N
from numpy._core.numeric import concatenate, isscalar

# 虽然 matrix_power 不在 __all__ 中,但为了向后兼容性,我们仍从 numpy.linalg 中导入
from numpy.linalg import matrix_power


def _convert_from_string(data):
    # 清理数据中的 '[]' 字符
    for char in '[]':
        data = data.replace(char, '')

    # 按行分割数据
    rows = data.split(';')
    newdata = []
    count = 0

    # 遍历每一行数据
    for row in rows:
        # 按逗号分割每行数据
        trow = row.split(',')
        newrow = []

        # 遍历每列数据
        for col in trow:
            # 按空格分割数据并进行字面评估,将结果扩展到新行中
            temp = col.split()
            newrow.extend(map(ast.literal_eval, temp))

        # 检查第一行的列数,确保所有行列数相同
        if count == 0:
            Ncols = len(newrow)
        elif len(newrow) != Ncols:
            raise ValueError("Rows not the same size.")

        count += 1
        newdata.append(newrow)

    return newdata


@set_module('numpy')
def asmatrix(data, dtype=None):
    """
    Interpret the input as a matrix.

    Unlike `matrix`, `asmatrix` does not make a copy if the input is already
    a matrix or an ndarray.  Equivalent to ``matrix(data, copy=False)``.

    Parameters
    ----------
    data : array_like
        Input data.
    dtype : data-type
       Data-type of the output matrix.

    Returns
    -------
    mat : matrix
        `data` interpreted as a matrix.

    Examples
    --------
    >>> x = np.array([[1, 2], [3, 4]])

    >>> m = np.asmatrix(x)

    >>> x[0,0] = 5

    >>> m
    matrix([[5, 2],
            [3, 4]])

    """
    # 调用 matrix 函数,将数据解释为矩阵,不进行拷贝操作
    return matrix(data, dtype=dtype, copy=False)


@set_module('numpy')
class matrix(N.ndarray):
    """
    matrix(data, dtype=None, copy=True)

    Returns a matrix from an array-like object, or from a string of data.

    A matrix is a specialized 2-D array that retains its 2-D nature
    through operations.  It has certain special operators, such as ``*``
    (matrix multiplication) and ``**`` (matrix power).

    .. note:: It is no longer recommended to use this class, even for linear
              algebra. Instead use regular arrays. The class may be removed
              in the future.

    Parameters
    ----------
    data : array_like or string
       If `data` is a string, it is interpreted as a matrix with commas
       or spaces separating columns, and semicolons separating rows.
    dtype : data-type
       Data-type of the output matrix.
    copy : bool
       If `data` is already an `ndarray`, then this flag determines
       whether the data is copied (the default), or whether a view is
       constructed.

    See Also
    --------
    array

    Examples
    --------
    >>> a = np.matrix('1 2; 3 4')
    >>> a
    matrix([[1, 2],
            [3, 4]])

    >>> np.matrix([[1, 2], [3, 4]])
    matrix([[1, 2],
            [3, 4]])

    """
    # 设置此类的数组优先级
    __array_priority__ = 10.0
    # 覆盖默认的构造方法 __new__,用于创建新的 matrix 对象
    def __new__(subtype, data, dtype=None, copy=True):
        # 发出警告,不推荐使用 matrix 子类表示矩阵或处理线性代数,建议使用普通的 ndarray
        warnings.warn('the matrix subclass is not the recommended way to '
                      'represent matrices or deal with linear algebra (see '
                      'https://docs.scipy.org/doc/numpy/user/'
                      'numpy-for-matlab-users.html). '
                      'Please adjust your code to use regular ndarray.',
                      PendingDeprecationWarning, stacklevel=2)
        # 如果输入数据已经是 matrix 类型,则根据条件返回原数据或者转换后的副本
        if isinstance(data, matrix):
            dtype2 = data.dtype
            if (dtype is None):
                dtype = dtype2
            if (dtype2 == dtype) and (not copy):
                return data
            return data.astype(dtype)

        # 如果输入数据是 ndarray 类型,则根据 dtype 参数和复制选项创建视图或副本
        if isinstance(data, N.ndarray):
            if dtype is None:
                intype = data.dtype
            else:
                intype = N.dtype(dtype)
            new = data.view(subtype)
            if intype != data.dtype:
                return new.astype(intype)
            if copy: return new.copy()
            else: return new

        # 如果输入数据是字符串,则调用 _convert_from_string 函数转换为数组
        if isinstance(data, str):
            data = _convert_from_string(data)

        # 将数据转换为数组 arr,根据其维度进行处理
        copy = None if not copy else True
        arr = N.array(data, dtype=dtype, copy=copy)
        ndim = arr.ndim
        shape = arr.shape

        # 检查矩阵维度是否为2,如果不是则引发 ValueError
        if (ndim > 2):
            raise ValueError("matrix must be 2-dimensional")
        elif ndim == 0:
            shape = (1, 1)
        elif ndim == 1:
            shape = (1, shape[0])

        # 矩阵默认的存储顺序为 'C' (按行优先),如果数组是列优先则设置为 'F'
        order = 'C'
        if (ndim == 2) and arr.flags.fortran:
            order = 'F'

        # 如果数组不是连续存储则进行复制操作
        if not (order or arr.flags.contiguous):
            arr = arr.copy()

        # 使用 ndarray 的构造方法创建新的 matrix 对象并返回
        ret = N.ndarray.__new__(subtype, shape, arr.dtype,
                                buffer=arr,
                                order=order)
        return ret

    # 定义 __array_finalize__ 方法,用于在数组 finalization 期间执行必要的处理
    def __array_finalize__(self, obj):
        # 设定标志位 _getitem 为 False
        self._getitem = False
        # 如果 obj 是 matrix 类型并且其 _getitem 标志为真,则返回
        if (isinstance(obj, matrix) and obj._getitem): return
        ndim = self.ndim
        # 如果矩阵维度为2,则直接返回
        if (ndim == 2):
            return
        # 如果矩阵维度大于2,则调整 shape 为符合条件的新形状
        if (ndim > 2):
            newshape = tuple([x for x in self.shape if x > 1])
            ndim = len(newshape)
            if ndim == 2:
                self.shape = newshape
                return
            elif (ndim > 2):
                raise ValueError("shape too large to be a matrix.")
        else:
            newshape = self.shape
        # 处理特殊情况下的维度调整
        if ndim == 0:
            self.shape = (1, 1)
        elif ndim == 1:
            self.shape = (1, newshape[0])
        return
    # 在实例化对象中通过索引访问元素时调用的特殊方法
    def __getitem__(self, index):
        # 标记正在执行 __getitem__ 操作
        self._getitem = True

        try:
            # 尝试使用基类 N.ndarray 的 __getitem__ 方法获取元素
            out = N.ndarray.__getitem__(self, index)
        finally:
            # 无论如何,标记 __getitem__ 操作结束
            self._getitem = False

        # 如果返回的不是 N.ndarray 类型的对象,直接返回
        if not isinstance(out, N.ndarray):
            return out

        # 如果返回的是 0 维数组,返回其零维数组中的元素
        if out.ndim == 0:
            return out[()]

        # 如果返回的是 1 维数组
        if out.ndim == 1:
            sh = out.shape[0]
            # 尝试获取索引的长度,用于判断是否应该返回列向量
            try:
                n = len(index)
            except Exception:
                n = 0

            # 如果索引长度大于 1 且第二个索引是标量,将数组形状调整为 sh x 1
            if n > 1 and isscalar(index[1]):
                out.shape = (sh, 1)
            else:
                # 否则将数组形状调整为 1 x sh
                out.shape = (1, sh)

        # 返回处理后的数组
        return out

    # 在对象与其他对象相乘时调用的特殊方法
    def __mul__(self, other):
        # 如果 other 是 N.ndarray, list 或 tuple 类型
        if isinstance(other, (N.ndarray, list, tuple)) :
            # 将 self 与 other 做点乘运算,并返回结果
            return N.dot(self, asmatrix(other))
        
        # 如果 other 是标量或者没有 __rmul__ 方法的对象
        if isscalar(other) or not hasattr(other, '__rmul__') :
            # 将 self 与 other 做点乘运算,并返回结果
            return N.dot(self, other)

        # 如果不支持的操作,返回 NotImplemented
        return NotImplemented

    # 在其他对象与对象相乘时调用的特殊方法
    def __rmul__(self, other):
        # 返回 other 与 self 的点乘结果
        return N.dot(other, self)

    # 实现对象就地乘法的特殊方法
    def __imul__(self, other):
        # 将对象自身乘以 other,并将结果赋值给自身
        self[:] = self * other
        return self

    # 实现对象的乘方运算的特殊方法
    def __pow__(self, other):
        # 调用 matrix_power 函数计算 self 的 other 次方,并返回结果
        return matrix_power(self, other)

    # 实现对象就地乘方运算的特殊方法
    def __ipow__(self, other):
        # 将对象自身做 other 次方运算,并将结果赋值给自身
        self[:] = self ** other
        return self

    # 在其他对象与对象乘方运算时调用的特殊方法
    def __rpow__(self, other):
        # 不支持的操作,返回 NotImplemented
        return NotImplemented

    # 对象在进行轴向对齐操作时调用的辅助函数
    def _align(self, axis):
        """A convenience function for operations that need to preserve axis
        orientation.
        """
        # 如果 axis 为 None,返回矩阵的左上角元素
        if axis is None:
            return self[0, 0]
        # 如果 axis 为 0,返回自身
        elif axis==0:
            return self
        # 如果 axis 为 1,返回自身的转置
        elif axis==1:
            return self.transpose()
        else:
            # 如果 axis 值不合法,抛出 ValueError 异常
            raise ValueError("unsupported axis")

    # 对象在进行轴向折叠操作时调用的辅助函数
    def _collapse(self, axis):
        """A convenience function for operations that want to collapse
        to a scalar like _align, but are using keepdims=True
        """
        # 如果 axis 为 None,返回矩阵的左上角元素
        if axis is None:
            return self[0, 0]
        else:
            # 其他情况返回自身
            return self

    # 重写基类 tolist 方法以支持矩阵对象的转换为列表操作
    def tolist(self):
        """
        Return the matrix as a (possibly nested) list.

        See `ndarray.tolist` for full documentation.

        See Also
        --------
        ndarray.tolist

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

        """
        # 调用 __array__ 方法将矩阵转换为 ndarray 后,再调用 ndarray 的 tolist 方法
        return self.__array__().tolist()

    # To preserve orientation of result...
    # 返回矩阵元素沿指定轴的和。
    def sum(self, axis=None, dtype=None, out=None):
        """
        Returns the sum of the matrix elements, along the given axis.

        Refer to `numpy.sum` for full documentation.

        See Also
        --------
        numpy.sum

        Notes
        -----
        This is the same as `ndarray.sum`, except that where an `ndarray` would
        be returned, a `matrix` object is returned instead.

        Examples
        --------
        >>> x = np.matrix([[1, 2], [4, 3]])
        >>> x.sum()
        10
        >>> x.sum(axis=1)
        matrix([[3],
                [7]])
        >>> x.sum(axis=1, dtype='float')
        matrix([[3.],
                [7.]])
        >>> out = np.zeros((2, 1), dtype='float')
        >>> x.sum(axis=1, dtype='float', out=np.asmatrix(out))
        matrix([[3.],
                [7.]])

        """
        return N.ndarray.sum(self, axis, dtype, out, keepdims=True)._collapse(axis)


    # 返回可能重新塑形的矩阵。
    def squeeze(self, axis=None):
        """
        Return a possibly reshaped matrix.

        Refer to `numpy.squeeze` for more documentation.

        Parameters
        ----------
        axis : None or int or tuple of ints, optional
            Selects a subset of the axes of length one in the shape.
            If an axis is selected with shape entry greater than one,
            an error is raised.

        Returns
        -------
        squeezed : matrix
            The matrix, but as a (1, N) matrix if it had shape (N, 1).

        See Also
        --------
        numpy.squeeze : related function

        Notes
        -----
        If `m` has a single column then that column is returned
        as the single row of a matrix.  Otherwise `m` is returned.
        The returned matrix is always either `m` itself or a view into `m`.
        Supplying an axis keyword argument will not affect the returned matrix
        but it may cause an error to be raised.

        Examples
        --------
        >>> c = np.matrix([[1], [2]])
        >>> c
        matrix([[1],
                [2]])
        >>> c.squeeze()
        matrix([[1, 2]])
        >>> r = c.T
        >>> r
        matrix([[1, 2]])
        >>> r.squeeze()
        matrix([[1, 2]])
        >>> m = np.matrix([[1, 2], [3, 4]])
        >>> m.squeeze()
        matrix([[1, 2],
                [3, 4]])

        """
        return N.ndarray.squeeze(self, axis=axis)
    def flatten(self, order='C'):
        """
        Return a flattened copy of the matrix.

        All `N` elements of the matrix are placed into a single row.

        Parameters
        ----------
        order : {'C', 'F', 'A', 'K'}, optional
            'C' means to flatten in row-major (C-style) order. 'F' means to
            flatten in column-major (Fortran-style) order. 'A' means to
            flatten in column-major order if `m` is Fortran *contiguous* in
            memory, row-major order otherwise. 'K' means to flatten `m` in
            the order the elements occur in memory. The default is 'C'.

        Returns
        -------
        y : matrix
            A copy of the matrix, flattened to a `(1, N)` matrix where `N`
            is the number of elements in the original matrix.

        See Also
        --------
        ravel : Return a flattened array.
        flat : A 1-D flat iterator over the matrix.

        Examples
        --------
        >>> m = np.matrix([[1,2], [3,4]])
        >>> m.flatten()
        matrix([[1, 2, 3, 4]])
        >>> m.flatten('F')
        matrix([[1, 3, 2, 4]])

        """
        # 调用 ndarray 类的 flatten 方法来对矩阵进行展平操作
        return N.ndarray.flatten(self, order=order)

    def mean(self, axis=None, dtype=None, out=None):
        """
        Returns the average of the matrix elements along the given axis.

        Refer to `numpy.mean` for full documentation.

        See Also
        --------
        numpy.mean

        Notes
        -----
        Same as `ndarray.mean` except that, where that returns an `ndarray`,
        this returns a `matrix` object.

        Examples
        --------
        >>> x = np.matrix(np.arange(12).reshape((3, 4)))
        >>> x
        matrix([[ 0,  1,  2,  3],
                [ 4,  5,  6,  7],
                [ 8,  9, 10, 11]])
        >>> x.mean()
        5.5
        >>> x.mean(0)
        matrix([[4., 5., 6., 7.]])
        >>> x.mean(1)
        matrix([[ 1.5],
                [ 5.5],
                [ 9.5]])

        """
        # 调用 ndarray 类的 mean 方法来计算矩阵元素的平均值,并返回一个 matrix 对象
        return N.ndarray.mean(self, axis, dtype, out, keepdims=True)._collapse(axis)
    def std(self, axis=None, dtype=None, out=None, ddof=0):
        """
        返回沿着给定轴的数组元素的标准差。

        参考 `numpy.std` 获取完整文档。

        See Also
        --------
        numpy.std

        Notes
        -----
        这与 `ndarray.std` 相同,不同之处在于 `ndarray` 返回时,返回的是一个 `matrix` 对象。

        Examples
        --------
        >>> x = np.matrix(np.arange(12).reshape((3, 4)))
        >>> x
        matrix([[ 0,  1,  2,  3],
                [ 4,  5,  6,  7],
                [ 8,  9, 10, 11]])
        >>> x.std()
        3.4520525295346629 # 可能有所不同
        >>> x.std(0)
        matrix([[ 3.26598632,  3.26598632,  3.26598632,  3.26598632]]) # 可能有所不同
        >>> x.std(1)
        matrix([[ 1.11803399],
                [ 1.11803399],
                [ 1.11803399]])

        """
        return N.ndarray.std(self, axis, dtype, out, ddof, keepdims=True)._collapse(axis)

    def var(self, axis=None, dtype=None, out=None, ddof=0):
        """
        返回沿着给定轴的矩阵元素的方差。

        参考 `numpy.var` 获取完整文档。

        See Also
        --------
        numpy.var

        Notes
        -----
        这与 `ndarray.var` 相同,不同之处在于 `ndarray` 返回时,返回的是一个 `matrix` 对象。

        Examples
        --------
        >>> x = np.matrix(np.arange(12).reshape((3, 4)))
        >>> x
        matrix([[ 0,  1,  2,  3],
                [ 4,  5,  6,  7],
                [ 8,  9, 10, 11]])
        >>> x.var()
        11.916666666666666
        >>> x.var(0)
        matrix([[ 10.66666667,  10.66666667,  10.66666667,  10.66666667]]) # 可能有所不同
        >>> x.var(1)
        matrix([[1.25],
                [1.25],
                [1.25]])

        """
        return N.ndarray.var(self, axis, dtype, out, ddof, keepdims=True)._collapse(axis)

    def prod(self, axis=None, dtype=None, out=None):
        """
        返回沿着给定轴的数组元素的乘积。

        参考 `prod` 获取完整文档。

        See Also
        --------
        prod, ndarray.prod

        Notes
        -----
        与 `ndarray.prod` 相同,不同之处在于 `ndarray` 返回时,返回的是一个 `matrix` 对象。

        Examples
        --------
        >>> x = np.matrix(np.arange(12).reshape((3,4))); x
        matrix([[ 0,  1,  2,  3],
                [ 4,  5,  6,  7],
                [ 8,  9, 10, 11]])
        >>> x.prod()
        0
        >>> x.prod(0)
        matrix([[  0,  45, 120, 231]])
        >>> x.prod(1)
        matrix([[   0],
                [ 840],
                [7920]])

        """
        return N.ndarray.prod(self, axis, dtype, out, keepdims=True)._collapse(axis)
    def any(self, axis=None, out=None):
        """
        Test whether any array element along a given axis evaluates to True.

        Refer to `numpy.any` for full documentation.

        Parameters
        ----------
        axis : int, optional
            Axis along which logical OR is performed
        out : ndarray, optional
            Output to existing array instead of creating new one, must have
            same shape as expected output

        Returns
        -------
        any : bool, ndarray
            Returns a single bool if `axis` is ``None``; otherwise,
            returns `ndarray`

        """
        # 调用 ndarray 类的 any 方法,用于检查数组元素在指定轴向上是否有 True 值,并保持维度信息
        return N.ndarray.any(self, axis, out, keepdims=True)._collapse(axis)

    def all(self, axis=None, out=None):
        """
        Test whether all matrix elements along a given axis evaluate to True.

        Parameters
        ----------
        See `numpy.all` for complete descriptions

        See Also
        --------
        numpy.all

        Notes
        -----
        This is the same as `ndarray.all`, but it returns a `matrix` object.

        Examples
        --------
        >>> x = np.matrix(np.arange(12).reshape((3,4))); x
        matrix([[ 0,  1,  2,  3],
                [ 4,  5,  6,  7],
                [ 8,  9, 10, 11]])
        >>> y = x[0]; y
        matrix([[0, 1, 2, 3]])
        >>> (x == y)
        matrix([[ True,  True,  True,  True],
                [False, False, False, False],
                [False, False, False, False]])
        >>> (x == y).all()
        False
        >>> (x == y).all(0)
        matrix([[False, False, False, False]])
        >>> (x == y).all(1)
        matrix([[ True],
                [False],
                [False]])

        """
        # 调用 ndarray 类的 all 方法,用于检查矩阵元素在指定轴向上是否全部为 True,并保持维度信息
        return N.ndarray.all(self, axis, out, keepdims=True)._collapse(axis)

    def max(self, axis=None, out=None):
        """
        Return the maximum value along an axis.

        Parameters
        ----------
        See `amax` for complete descriptions

        See Also
        --------
        amax, ndarray.max

        Notes
        -----
        This is the same as `ndarray.max`, but returns a `matrix` object
        where `ndarray.max` would return an ndarray.

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

        """
        # 调用 ndarray 类的 max 方法,返回沿指定轴向的最大值,并保持维度信息
        return N.ndarray.max(self, axis, out, keepdims=True)._collapse(axis)
    def argmax(self, axis=None, out=None):
        """
        返回沿着指定轴的最大值的索引。

        返回沿着指定轴的最大值的第一个出现的索引。如果 axis 是 None,则索引是针对展平的矩阵。

        Parameters
        ----------
        axis : int, optional
            沿着哪个轴查找最大值的索引。默认为 None。
        out : ndarray, optional
            结果的放置位置。默认为 None。

        See Also
        --------
        numpy.argmax

        Notes
        -----
        这与 `ndarray.argmax` 相同,但返回一个 `matrix` 对象,而 `ndarray.argmax` 返回一个 `ndarray`。

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

        """
        return N.ndarray.argmax(self, axis, out)._align(axis)

    def min(self, axis=None, out=None):
        """
        返回沿着指定轴的最小值。

        Parameters
        ----------
        axis : int, optional
            沿着哪个轴查找最小值。默认为 None。
        out : ndarray, optional
            结果的放置位置。默认为 None。

        See Also
        --------
        numpy.amin, ndarray.min

        Notes
        -----
        这与 `ndarray.min` 相同,但返回一个 `matrix` 对象,而 `ndarray.min` 返回一个 `ndarray`。

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

        """
        return N.ndarray.min(self, axis, out, keepdims=True)._collapse(axis)

    def argmin(self, axis=None, out=None):
        """
        返回沿着指定轴的最小值的索引。

        返回沿着指定轴的最小值的第一个出现的索引。如果 axis 是 None,则索引是针对展平的矩阵。

        Parameters
        ----------
        axis : int, optional
            沿着哪个轴查找最小值的索引。默认为 None。
        out : ndarray, optional
            结果的放置位置。默认为 None。

        See Also
        --------
        numpy.argmin

        Notes
        -----
        这与 `ndarray.argmin` 相同,但返回一个 `matrix` 对象,而 `ndarray.argmin` 返回一个 `ndarray`。

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

        """
        return N.ndarray.argmin(self, axis, out)._align(axis)
    def ptp(self, axis=None, out=None):
        """
        Peak-to-peak (maximum - minimum) value along the given axis.

        Refer to `numpy.ptp` for full documentation.

        See Also
        --------
        numpy.ptp

        Notes
        -----
        Same as `ndarray.ptp`, except, where that would return an `ndarray` object,
        this returns a `matrix` object.

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

        """
        return N.ptp(self, axis, out)._align(axis)



    @property
    def I(self):
        """
        Returns the (multiplicative) inverse of invertible `self`.

        Parameters
        ----------
        None

        Returns
        -------
        ret : matrix object
            If `self` is non-singular, `ret` is such that ``ret * self`` ==
            ``self * ret`` == ``np.matrix(np.eye(self[0,:].size))`` all return
            ``True``.

        Raises
        ------
        numpy.linalg.LinAlgError: Singular matrix
            If `self` is singular.

        See Also
        --------
        linalg.inv

        Examples
        --------
        >>> m = np.matrix('[1, 2; 3, 4]'); m
        matrix([[1, 2],
                [3, 4]])
        >>> m.getI()
        matrix([[-2. ,  1. ],
                [ 1.5, -0.5]])
        >>> m.getI() * m
        matrix([[ 1.,  0.], # may vary
                [ 0.,  1.]])

        """
        M, N = self.shape
        if M == N:
            from numpy.linalg import inv as func
        else:
            from numpy.linalg import pinv as func
        return asmatrix(func(self))



    @property
    def A(self):
        """
        Return `self` as an `ndarray` object.

        Equivalent to ``np.asarray(self)``.

        Parameters
        ----------
        None

        Returns
        -------
        ret : ndarray
            `self` as an `ndarray`

        Examples
        --------
        >>> x = np.matrix(np.arange(12).reshape((3,4))); x
        matrix([[ 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]])

        """
        return self.__array__()



    @property
    def H(self):
        """
        Return the conjugate transpose of `self`.

        Equivalent to ``np.asarray(self).conj().T``.

        Parameters
        ----------
        None

        Returns
        -------
        ret : matrix
            Conjugate transpose of `self`

        Examples
        --------
        >>> x = np.matrix([[1+1j, 2+2j], [3+3j, 4+4j]])
        >>> x.H
        matrix([[1.-1.j, 3.-3.j],
                [2.-2.j, 4.-4.j]])

        """
        return self.__array__().conj().T
    def A1(self):
        """
        Return `self` as a flattened `ndarray`.

        Equivalent to ``np.asarray(x).ravel()``

        Parameters
        ----------
        None

        Returns
        -------
        ret : ndarray
            `self`, 1-D, as an `ndarray`

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


        """
        # 返回当前对象作为一个扁平化的 ndarray
        return self.__array__().ravel()


    def ravel(self, order='C'):
        """
        Return a flattened matrix.

        Refer to `numpy.ravel` for more documentation.

        Parameters
        ----------
        order : {'C', 'F', 'A', 'K'}, optional
            The elements of `m` are read using this index order. 'C' means to
            index the elements in C-like order, with the last axis index
            changing fastest, back to the first axis index changing slowest.
            'F' means to index the elements in Fortran-like index order, with
            the first index changing fastest, and the last index changing
            slowest. Note that the 'C' and 'F' options take no account of the
            memory layout of the underlying array, and only refer to the order
            of axis indexing.  'A' means to read the elements in Fortran-like
            index order if `m` is Fortran *contiguous* in memory, C-like order
            otherwise.  'K' means to read the elements in the order they occur
            in memory, except for reversing the data when strides are negative.
            By default, 'C' index order is used.

        Returns
        -------
        ret : matrix
            Return the matrix flattened to shape `(1, N)` where `N`
            is the number of elements in the original matrix.
            A copy is made only if necessary.

        See Also
        --------
        matrix.flatten : returns a similar output matrix but always a copy
        matrix.flat : a flat iterator on the array.
        numpy.ravel : related function which returns an ndarray

        """
        # 调用 N.ndarray.ravel 方法将当前对象扁平化,按指定顺序排列
        return N.ndarray.ravel(self, order=order)

    @property
    def T(self):
        """
        Returns the transpose of the matrix.

        Does *not* conjugate!  For the complex conjugate transpose, use ``.H``.

        Parameters
        ----------
        None

        Returns
        -------
        ret : matrix object
            The (non-conjugated) transpose of the matrix.

        See Also
        --------
        transpose, getH

        Examples
        --------
        >>> m = np.matrix('[1, 2; 3, 4]')
        >>> m
        matrix([[1, 2],
                [3, 4]])
        >>> m.getT()
        matrix([[1, 3],
                [2, 4]])

        """
        # 返回当前对象的转置矩阵
        return self.transpose()

    @property
    # 为对象的复共轭转置提供访问器方法

    # getT 访问器方法返回转置后的矩阵,已经废弃,保留仅用于兼容性
    getT = T.fget

    # getA 访问器方法返回矩阵自身的副本,已经废弃,保留仅用于兼容性
    getA = A.fget

    # getA1 访问器方法返回矩阵的第一个基类,已经废弃,保留仅用于兼容性
    getA1 = A1.fget

    # getH 访问器方法返回矩阵的复共轭转置
    getH = H.fget

    # getI 访问器方法返回矩阵的逆矩阵,已经废弃,保留仅用于兼容性
    getI = I.fget
# 如果输入对象是字符串,则根据全局或局部字典创建矩阵对象
def bmat(obj, ldict=None, gdict=None):
    """
    Build a matrix object from a string, nested sequence, or array.

    Parameters
    ----------
    obj : str or array_like
        Input data. If a string, variables in the current scope may be
        referenced by name.
    ldict : dict, optional
        A dictionary that replaces local operands in current frame.
        Ignored if `obj` is not a string or `gdict` is None.
    gdict : dict, optional
        A dictionary that replaces global operands in current frame.
        Ignored if `obj` is not a string.

    Returns
    -------
    out : matrix
        Returns a matrix object, which is a specialized 2-D array.

    See Also
    --------
    block :
        A generalization of this function for N-d arrays, that returns normal
        ndarrays.

    Examples
    --------
    >>> A = np.asmatrix('1 1; 1 1')
    >>> B = np.asmatrix('2 2; 2 2')
    >>> C = np.asmatrix('3 4; 5 6')
    >>> D = np.asmatrix('7 8; 9 0')

    All the following expressions construct the same block matrix:

    >>> np.bmat([[A, B], [C, D]])
    matrix([[1, 1, 2, 2],
            [1, 1, 2, 2],
            [3, 4, 7, 8],
            [5, 6, 9, 0]])
    >>> np.bmat(np.r_[np.c_[A, B], np.c_[C, D]])
    matrix([[1, 1, 2, 2],
            [1, 1, 2, 2],
            [3, 4, 7, 8],
            [5, 6, 9, 0]])
    >>> np.bmat('A,B; C,D')
    matrix([[1, 1, 2, 2],
            [1, 1, 2, 2],
            [3, 4, 7, 8],
            [5, 6, 9, 0]])

    """
    if isinstance(obj, str):
        # 如果对象是字符串,则根据全局或局部字典创建矩阵对象
        if gdict is None:
            # 获取上一个调用帧的全局和局部字典
            frame = sys._getframe().f_back
            glob_dict = frame.f_globals
            loc_dict = frame.f_locals
        else:
            glob_dict = gdict
            loc_dict = ldict

        # 调用内部函数 _from_string 将字符串转换为矩阵对象并返回
        return matrix(_from_string(obj, glob_dict, loc_dict))

    if isinstance(obj, (tuple, list)):
        # 如果对象是元组或列表,则根据内容创建矩阵对象
        arr_rows = []
        for row in obj:
            if isinstance(row, N.ndarray):  # 如果行是数组而不是二维数组
                # 直接拼接对象返回矩阵对象
                return matrix(concatenate(obj, axis=-1))
            else:
                # 将每行的数组对象拼接并存储
                arr_rows.append(concatenate(row, axis=-1))
        # 拼接所有行数组对象并返回矩阵对象
        return matrix(concatenate(arr_rows, axis=0))
    if isinstance(obj, N.ndarray):
        # 如果对象是数组,则直接返回矩阵对象
        return matrix(obj)

.\numpy\numpy\matrixlib\defmatrix.pyi

# 导入必要的模块和类型定义
from collections.abc import Sequence, Mapping  # 导入 collections.abc 模块中的 Sequence 和 Mapping
from typing import Any  # 导入 typing 模块中的 Any 类型
from numpy import matrix as matrix  # 从 numpy 中导入 matrix 类,并将其命名为 matrix
from numpy._typing import ArrayLike, DTypeLike, NDArray  # 导入 numpy._typing 中的 ArrayLike, DTypeLike 和 NDArray 类型

__all__: list[str]  # 定义 __all__ 变量,类型为 list,其中元素类型为 str

# 定义函数 bmat,接受一个字符串、数组类别的序列或 NDArray 类型的对象,
# 并可选地接受一个局部字典和全局字典,返回一个 numpy matrix 类型的对象
def bmat(
    obj: str | Sequence[ArrayLike] | NDArray[Any],  # obj 参数可以是 str、Sequence[ArrayLike] 或 NDArray[Any] 类型
    ldict: None | Mapping[str, Any] = ...,  # ldict 参数可选,可以是 None 或 Mapping[str, Any] 类型,默认值为省略号
    gdict: None | Mapping[str, Any] = ...,  # gdict 参数可选,可以是 None 或 Mapping[str, Any] 类型,默认值为省略号
) -> matrix[Any, Any]:  # 函数返回一个 numpy matrix 类型,可以包含任意类型的数据

# 定义函数 asmatrix,接受一个 ArrayLike 类型的数据和一个可选的 dtype 参数,
# 返回一个 numpy matrix 类型的对象
def asmatrix(data: ArrayLike, dtype: DTypeLike = ...) -> matrix[Any, Any]:  # data 参数是 ArrayLike 类型,dtype 参数是 DTypeLike 类型,默认值为省略号

mat = asmatrix  # 将 asmatrix 函数赋值给 mat 变量

.\numpy\numpy\matrixlib\tests\test_defmatrix.py

import collections.abc  # 导入 collections.abc 模块

import numpy as np  # 导入 NumPy 库
from numpy import matrix, asmatrix, bmat  # 从 NumPy 导入 matrix, asmatrix, bmat 函数
from numpy.testing import (  # 导入 NumPy 测试模块中的多个断言函数
    assert_, assert_equal, assert_almost_equal, assert_array_equal,
    assert_array_almost_equal, assert_raises
    )
from numpy.linalg import matrix_power  # 导入 NumPy 线性代数模块中的 matrix_power 函数

class TestCtor:  # 定义测试类 TestCtor
    def test_basic(self):  # 定义测试基本功能的方法 test_basic
        A = np.array([[1, 2], [3, 4]])  # 创建 NumPy 数组 A
        mA = matrix(A)  # 使用 matrix 函数创建矩阵对象 mA
        assert_(np.all(mA.A == A))  # 断言矩阵对象 mA 的数据与数组 A 相同

        B = bmat("A,A;A,A")  # 使用 bmat 函数创建块矩阵 B
        C = bmat([[A, A], [A, A]])  # 使用 bmat 函数创建块矩阵 C
        D = np.array([[1, 2, 1, 2],  # 创建数组 D
                      [3, 4, 3, 4],
                      [1, 2, 1, 2],
                      [3, 4, 3, 4]])
        assert_(np.all(B.A == D))  # 断言块矩阵 B 的数据与数组 D 相同
        assert_(np.all(C.A == D))  # 断言块矩阵 C 的数据与数组 D 相同

        E = np.array([[5, 6], [7, 8]])  # 创建数组 E
        AEresult = matrix([[1, 2, 5, 6], [3, 4, 7, 8]])  # 创建期望的矩阵 AEresult
        assert_(np.all(bmat([A, E]) == AEresult))  # 断言块矩阵 [A, E] 与 AEresult 相同

        vec = np.arange(5)  # 创建 NumPy 数组 vec
        mvec = matrix(vec)  # 使用 matrix 函数创建矩阵对象 mvec
        assert_(mvec.shape == (1, 5))  # 断言矩阵对象 mvec 的形状为 (1, 5)

    def test_exceptions(self):  # 定义测试异常情况的方法 test_exceptions
        # 检查当传入无效字符串数据时是否引发 ValueError 异常
        assert_raises(ValueError, matrix, "invalid")

    def test_bmat_nondefault_str(self):  # 定义测试非默认字符串的方法 test_bmat_nondefault_str
        A = np.array([[1, 2], [3, 4]])  # 创建 NumPy 数组 A
        B = np.array([[5, 6], [7, 8]])  # 创建 NumPy 数组 B
        Aresult = np.array([[1, 2, 1, 2],  # 创建期望的数组 Aresult
                            [3, 4, 3, 4],
                            [1, 2, 1, 2],
                            [3, 4, 3, 4]])
        mixresult = np.array([[1, 2, 5, 6],  # 创建期望的数组 mixresult
                              [3, 4, 7, 8],
                              [5, 6, 1, 2],
                              [7, 8, 3, 4]])
        assert_(np.all(bmat("A,A;A,A") == Aresult))  # 断言块矩阵 "A,A;A,A" 与 Aresult 相同
        assert_(np.all(bmat("A,A;A,A", ldict={'A':B}) == Aresult))  # 断言使用局部字典的块矩阵与 Aresult 相同
        assert_raises(TypeError, bmat, "A,A;A,A", gdict={'A':B})  # 检查当使用全局字典时是否引发 TypeError 异常
        assert_(  # 断言使用局部和全局字典的块矩阵与 Aresult 相同
            np.all(bmat("A,A;A,A", ldict={'A':A}, gdict={'A':B}) == Aresult))
        b2 = bmat("A,B;C,D", ldict={'A':A,'B':B}, gdict={'C':B,'D':A})  # 创建块矩阵 b2
        assert_(np.all(b2 == mixresult))  # 断言块矩阵 b2 与 mixresult 相同


class TestProperties:  # 定义测试属性的类 TestProperties
    def test_sum(self):  # 定义测试求和方法 test_sum
        """Test whether matrix.sum(axis=1) preserves orientation.
        Fails in NumPy <= 0.9.6.2127.
        """
        M = matrix([[1, 2, 0, 0],  # 创建矩阵 M
                   [3, 4, 0, 0],
                   [1, 2, 1, 2],
                   [3, 4, 3, 4]])
        sum0 = matrix([8, 12, 4, 6])  # 创建期望的列求和结果 sum0
        sum1 = matrix([3, 7, 6, 14]).T  # 创建期望的行求和结果 sum1
        sumall = 30  # 创建期望的总和结果 sumall
        assert_array_equal(sum0, M.sum(axis=0))  # 断言矩阵 M 按列求和结果与 sum0 相同
        assert_array_equal(sum1, M.sum(axis=1))  # 断言矩阵 M 按行求和结果与 sum1 相同
        assert_equal(sumall, M.sum())  # 断言矩阵 M 总和与 sumall 相同

        assert_array_equal(sum0, np.sum(M, axis=0))  # 断言使用 NumPy 求和函数的列求和结果与 sum0 相同
        assert_array_equal(sum1, np.sum(M, axis=1))  # 断言使用 NumPy 求和函数的行求和结果与 sum1 相同
        assert_equal(sumall, np.sum(M))  # 断言使用 NumPy 求和函数的总和与 sumall 相同
    def test_prod(self):
        # 创建一个 2x3 的矩阵 x
        x = matrix([[1, 2, 3], [4, 5, 6]])
        # 断言矩阵 x 所有元素的乘积为 720
        assert_equal(x.prod(), 720)
        # 断言按列计算 x 的乘积,结果是一个矩阵
        assert_equal(x.prod(0), matrix([[4, 10, 18]]))
        # 断言按行计算 x 的乘积,结果是一个矩阵
        assert_equal(x.prod(1), matrix([[6], [120]]))

        # 使用 numpy 计算矩阵 x 的所有元素的乘积
        assert_equal(np.prod(x), 720)
        # 使用 numpy 按列计算矩阵 x 的乘积,结果是一个矩阵
        assert_equal(np.prod(x, axis=0), matrix([[4, 10, 18]]))
        # 使用 numpy 按行计算矩阵 x 的乘积,结果是一个矩阵
        assert_equal(np.prod(x, axis=1), matrix([[6], [120]]))

        # 创建一个包含元素 0, 1, 3 的矩阵 y
        y = matrix([0, 1, 3])
        # 断言矩阵 y 所有元素的乘积为 0
        assert_(y.prod() == 0)

    def test_max(self):
        # 创建一个 2x3 的矩阵 x
        x = matrix([[1, 2, 3], [4, 5, 6]])
        # 断言矩阵 x 的最大值为 6
        assert_equal(x.max(), 6)
        # 断言按列找出 x 的最大值,结果是一个矩阵
        assert_equal(x.max(0), matrix([[4, 5, 6]]))
        # 断言按行找出 x 的最大值,结果是一个矩阵
        assert_equal(x.max(1), matrix([[3], [6]]))

        # 使用 numpy 找出矩阵 x 的最大值
        assert_equal(np.max(x), 6)
        # 使用 numpy 按列找出矩阵 x 的最大值,结果是一个矩阵
        assert_equal(np.max(x, axis=0), matrix([[4, 5, 6]]))
        # 使用 numpy 按行找出矩阵 x 的最大值,结果是一个矩阵
        assert_equal(np.max(x, axis=1), matrix([[3], [6]]))

    def test_min(self):
        # 创建一个 2x3 的矩阵 x
        x = matrix([[1, 2, 3], [4, 5, 6]])
        # 断言矩阵 x 的最小值为 1
        assert_equal(x.min(), 1)
        # 断言按列找出 x 的最小值,结果是一个矩阵
        assert_equal(x.min(0), matrix([[1, 2, 3]]))
        # 断言按行找出 x 的最小值,结果是一个矩阵
        assert_equal(x.min(1), matrix([[1], [4]]))

        # 使用 numpy 找出矩阵 x 的最小值
        assert_equal(np.min(x), 1)
        # 使用 numpy 按列找出矩阵 x 的最小值,结果是一个矩阵
        assert_equal(np.min(x, axis=0), matrix([[1, 2, 3]]))
        # 使用 numpy 按行找出矩阵 x 的最小值,结果是一个矩阵
        assert_equal(np.min(x, axis=1), matrix([[1], [4]]))

    def test_ptp(self):
        # 创建一个 2x2 的 numpy 数组 x
        x = np.arange(4).reshape((2, 2))
        # 将数组 x 转换为矩阵 mx
        mx = x.view(np.matrix)
        # 断言矩阵 mx 的最大值与最小值之差为 3
        assert_(mx.ptp() == 3)
        # 断言按列计算矩阵 mx 的最大值与最小值之差,结果是一个数组
        assert_(np.all(mx.ptp(0) == np.array([2, 2])))
        # 断言按行计算矩阵 mx 的最大值与最小值之差,结果是一个数组
        assert_(np.all(mx.ptp(1) == np.array([1, 1])))

    def test_var(self):
        # 创建一个 3x3 的 numpy 数组 x
        x = np.arange(9).reshape((3, 3))
        # 将数组 x 转换为矩阵 mx
        mx = x.view(np.matrix)
        # 断言矩阵 mx 的方差,无偏估计(自由度为 0)
        assert_equal(x.var(ddof=0), mx.var(ddof=0))
        # 断言矩阵 mx 的方差,无偏估计(自由度为 1)
        assert_equal(x.var(ddof=1), mx.var(ddof=1))

    def test_basic(self):
        import numpy.linalg as linalg

        # 创建一个 2x2 的 numpy 数组 A
        A = np.array([[1., 2.],
                      [3., 4.]])
        # 将数组 A 转换为矩阵 mA
        mA = matrix(A)
        # 断言数组 A 的逆与矩阵 mA 的逆相等
        assert_(np.allclose(linalg.inv(A), mA.I))
        # 断言数组 A 的转置与矩阵 mA 的转置相等
        assert_(np.all(np.array(np.transpose(A) == mA.T)))
        # 断言数组 A 的转置与矩阵 mA 的共轭转置相等
        assert_(np.all(np.array(np.transpose(A) == mA.H)))
        # 断言数组 A 与矩阵 mA 的元素相等
        assert_(np.all(A == mA.A))

        # 创建一个复数数组 B
        B = A + 2j*A
        # 将数组 B 转换为矩阵 mB
        mB = matrix(B)
        # 断言复数数组 B 的逆与矩阵 mB 的逆相等
        assert_(np.allclose(linalg.inv(B), mB.I))
        # 断言复数数组 B 的转置与矩阵 mB 的转置相等
        assert_(np.all(np.array(np.transpose(B) == mB.T)))
        # 断言复数数组 B 的转置的共轭与矩阵 mB 的共轭转置相等
        assert_(np.all(np.array(np.transpose(B).conj() == mB.H)))

    def test_pinv(self):
        # 创建一个 2x3 的矩阵 x
        x = matrix(np.arange(6).reshape(2, 3))
        # 预计 x 的伪逆矩阵为 xpinv
        xpinv = matrix([[-0.77777778,  0.27777778],
                        [-0.11111111,  0.11111111],
                        [ 0.55555556, -0.05555556]])
        # 断言矩阵 x 的伪逆与预期的 xpinv 相近
        assert_almost_equal(x.I, xpinv)
    def test_comparisons(self):
        A = np.arange(100).reshape(10, 10)
        mA = matrix(A)
        mB = matrix(A) + 0.1
        assert_(np.all(mB == A+0.1))  # 检查矩阵 mB 的所有元素是否与 A+0.1 中的对应元素相等
        assert_(np.all(mB == matrix(A+0.1)))  # 检查矩阵 mB 是否与由 A+0.1 创建的矩阵相等
        assert_(not np.any(mB == matrix(A-0.1)))  # 检查矩阵 mB 是否有任何元素与由 A-0.1 创建的矩阵相等
        assert_(np.all(mA < mB))  # 检查矩阵 mA 的所有元素是否小于矩阵 mB 的对应元素
        assert_(np.all(mA <= mB))  # 检查矩阵 mA 的所有元素是否小于或等于矩阵 mB 的对应元素
        assert_(np.all(mA <= mA))  # 检查矩阵 mA 的所有元素是否小于或等于自身的对应元素
        assert_(not np.any(mA < mA))  # 检查矩阵 mA 是否有任何元素小于自身的对应元素

        assert_(not np.any(mB < mA))  # 检查矩阵 mB 是否有任何元素小于矩阵 mA 的对应元素
        assert_(np.all(mB >= mA))  # 检查矩阵 mB 的所有元素是否大于或等于矩阵 mA 的对应元素
        assert_(np.all(mB >= mB))  # 检查矩阵 mB 的所有元素是否大于或等于自身的对应元素
        assert_(not np.any(mB > mB))  # 检查矩阵 mB 是否有任何元素大于自身的对应元素

        assert_(np.all(mA == mA))  # 检查矩阵 mA 的所有元素是否与自身的对应元素相等
        assert_(not np.any(mA == mB))  # 检查矩阵 mA 是否有任何元素与矩阵 mB 的对应元素相等
        assert_(np.all(mB != mA))  # 检查矩阵 mB 的所有元素是否与矩阵 mA 的对应元素不相等

        assert_(not np.all(abs(mA) > 0))  # 检查矩阵 mA 是否所有元素的绝对值都大于 0
        assert_(np.all(abs(mB > 0)))  # 检查矩阵 mB 是否所有元素的绝对值都大于 0

    def test_asmatrix(self):
        A = np.arange(100).reshape(10, 10)
        mA = asmatrix(A)
        A[0, 0] = -10
        assert_(A[0, 0] == mA[0, 0])  # 检查通过 asmatrix 创建的矩阵 mA 的第一个元素是否与原始数组 A 中相应位置的元素相同

    def test_noaxis(self):
        A = matrix([[1, 0], [0, 1]])
        assert_(A.sum() == matrix(2))  # 检查矩阵 A 所有元素之和是否等于矩阵(2)
        assert_(A.mean() == matrix(0.5))  # 检查矩阵 A 所有元素的平均值是否等于矩阵(0.5)

    def test_repr(self):
        A = matrix([[1, 0], [0, 1]])
        assert_(repr(A) == "matrix([[1, 0],\n        [0, 1]])")  # 检查矩阵 A 的字符串表示形式是否符合预期格式

    def test_make_bool_matrix_from_str(self):
        A = matrix('True; True; False')
        B = matrix([[True], [True], [False]])
        assert_array_equal(A, B)  # 检查从字符串创建的布尔矩阵 A 是否与手动创建的布尔矩阵 B 相等
class TestCasting:
    def test_basic(self):
        A = np.arange(100).reshape(10, 10)
        mA = matrix(A)  # 将numpy数组A转换为matrix对象mA

        mB = mA.copy()  # 复制mA得到mB
        O = np.ones((10, 10), np.float64) * 0.1  # 创建一个全为0.1的10x10浮点数数组O
        mB = mB + O  # 将mB中的每个元素加上对应的O中的元素
        assert_(mB.dtype.type == np.float64)  # 断言mB的数据类型为np.float64
        assert_(np.all(mA != mB))  # 断言mA和mB中所有元素不相等
        assert_(np.all(mB == mA+0.1))  # 断言mB中所有元素与mA中所有元素加0.1后相等

        mC = mA.copy()  # 复制mA得到mC
        O = np.ones((10, 10), np.complex128)  # 创建一个全为1的10x10复数数组O
        mC = mC * O  # 将mC中的每个元素与对应的O中的元素相乘
        assert_(mC.dtype.type == np.complex128)  # 断言mC的数据类型为np.complex128
        assert_(np.all(mA != mB))  # 断言mA和mB中所有元素不相等


class TestAlgebra:
    def test_basic(self):
        import numpy.linalg as linalg

        A = np.array([[1., 2.], [3., 4.]])  # 创建一个2x2的numpy数组A
        mA = matrix(A)  # 将数组A转换为matrix对象mA

        B = np.identity(2)  # 创建一个2x2的单位矩阵B
        for i in range(6):
            assert_(np.allclose((mA ** i).A, B))  # 断言mA的i次方的数组表示与B的所有元素近似相等
            B = np.dot(B, A)  # 更新B为B与A的矩阵乘积

        Ainv = linalg.inv(A)  # 计算A的逆矩阵
        B = np.identity(2)  # 重新初始化B为单位矩阵
        for i in range(6):
            assert_(np.allclose((mA ** -i).A, B))  # 断言mA的-i次方的数组表示与B的所有元素近似相等
            B = np.dot(B, Ainv)  # 更新B为B与A的逆矩阵的矩阵乘积

        assert_(np.allclose((mA * mA).A, np.dot(A, A)))  # 断言mA的平方的数组表示与A与A的矩阵乘积的所有元素近似相等
        assert_(np.allclose((mA + mA).A, (A + A)))  # 断言mA与mA的数组表示与A与A的数组表示的和的所有元素近似相等
        assert_(np.allclose((3*mA).A, (3*A)))  # 断言3乘以mA的数组表示与3乘以A的所有元素近似相等

        mA2 = matrix(A)  # 将数组A重新转换为matrix对象mA2
        mA2 *= 3  # 将mA2中的每个元素乘以3
        assert_(np.allclose(mA2.A, 3*A))  # 断言mA2的数组表示与3乘以A的所有元素近似相等

    def test_pow(self):
        """Test raising a matrix to an integer power works as expected."""
        m = matrix("1. 2.; 3. 4.")  # 创建一个2x2的matrix对象m
        m2 = m.copy()  # 复制m得到m2
        m2 **= 2  # 计算m2的平方
        mi = m.copy()  # 复制m得到mi
        mi **= -1  # 计算mi的逆矩阵
        m4 = m2.copy()  # 复制m2得到m4
        m4 **= 2  # 计算m4的平方
        assert_array_almost_equal(m2, m**2)  # 断言m2与m的平方的所有元素近似相等
        assert_array_almost_equal(m4, np.dot(m2, m2))  # 断言m4与m2的矩阵乘积的数组表示的所有元素近似相等
        assert_array_almost_equal(np.dot(mi, m), np.eye(2))  # 断言mi与m的矩阵乘积的数组表示与2x2单位矩阵的所有元素近似相等

    def test_scalar_type_pow(self):
        m = matrix([[1, 2], [3, 4]])  # 创建一个2x2的matrix对象m
        for scalar_t in [np.int8, np.uint8]:
            two = scalar_t(2)  # 创建一个特定类型的标量two
            assert_array_almost_equal(m ** 2, m ** two)  # 断言m的平方与m的two次方的所有元素近似相等

    def test_notimplemented(self):
        '''Check that 'not implemented' operations produce a failure.'''
        A = matrix([[1., 2.],
                    [3., 4.]])  # 创建一个2x2的matrix对象A

        # __rpow__
        with assert_raises(TypeError):
            1.0**A  # 尝试使用浮点数对matrix对象A进行反向乘方操作,断言预期的TypeError异常

        # __mul__ with something not a list, ndarray, tuple, or scalar
        with assert_raises(TypeError):
            A*object()  # 尝试将matrix对象A与非列表、ndarray、元组或标量相乘,断言预期的TypeError异常


class TestMatrixReturn:
    # 测试矩阵实例方法的功能
    def test_instance_methods(self):
        # 创建一个包含单个浮点数的矩阵
        a = matrix([1.0], dtype='f8')
        # 定义方法参数的字典,用于调用实例方法
        methodargs = {
            'astype': ('intc',),
            'clip': (0.0, 1.0),
            'compress': ([1],),
            'repeat': (1,),
            'reshape': (1,),
            'swapaxes': (0, 0),
            'dot': np.array([1.0]),
            }
        # 排除的方法列表,这些方法不会被测试
        excluded_methods = [
            'argmin', 'choose', 'dump', 'dumps', 'fill', 'getfield',
            'getA', 'getA1', 'item', 'nonzero', 'put', 'putmask', 'resize',
            'searchsorted', 'setflags', 'setfield', 'sort',
            'partition', 'argpartition', 'newbyteorder', 'to_device',
            'take', 'tofile', 'tolist', 'tostring', 'tobytes', 'all', 'any',
            'sum', 'argmax', 'argmin', 'min', 'max', 'mean', 'var', 'ptp',
            'prod', 'std', 'ctypes', 'itemset', 'bitwise_count',
            ]
        # 遍历矩阵对象的所有属性
        for attrib in dir(a):
            # 排除私有属性和在排除列表中的方法
            if attrib.startswith('_') or attrib in excluded_methods:
                continue
            # 获取属性对应的方法对象
            f = getattr(a, attrib)
            # 如果该属性是可调用的方法
            if isinstance(f, collections.abc.Callable):
                # 重置矩阵内容为浮点类型
                a.astype('f8')
                # 将矩阵填充为全部为1.0
                a.fill(1.0)
                # 如果该方法在methodargs中有参数定义,就使用这些参数
                if attrib in methodargs:
                    args = methodargs[attrib]
                else:
                    args = ()
                # 调用方法并获取返回值
                b = f(*args)
                # 断言返回值的类型是矩阵类型
                assert_(type(b) is matrix, "%s" % attrib)
        # 断言实部和虚部仍然是矩阵类型
        assert_(type(a.real) is matrix)
        assert_(type(a.imag) is matrix)
        # 计算矩阵中非零元素的索引
        c, d = matrix([0.0]).nonzero()
        # 断言索引c和d的类型是NumPy数组
        assert_(type(c) is np.ndarray)
        assert_(type(d) is np.ndarray)
class TestIndexing:
    # 测试类,用于测试索引操作

    def test_basic(self):
        # 基本测试方法
        x = asmatrix(np.zeros((3, 2), float))
        # 创建一个3x2的零矩阵,并将其转换为矩阵对象
        y = np.zeros((3, 1), float)
        # 创建一个3x1的零数组
        y[:, 0] = [0.8, 0.2, 0.3]
        # 将数组y的第一列分别设置为0.8, 0.2, 0.3
        x[:, 1] = y > 0.5
        # 将矩阵x的第二列根据y > 0.5的条件进行布尔索引赋值
        assert_equal(x, [[0, 1], [0, 0], [0, 0]])
        # 断言矩阵x与期望值[[0, 1], [0, 0], [0, 0]]相等


class TestNewScalarIndexing:
    # 测试新的标量索引类

    a = matrix([[1, 2], [3, 4]])
    # 创建一个2x2的矩阵a

    def test_dimesions(self):
        # 测试矩阵维度方法
        a = self.a
        # 从测试类属性中获取矩阵a
        x = a[0]
        # 获取矩阵a的第一行
        assert_equal(x.ndim, 2)
        # 断言x的维度为2

    def test_array_from_matrix_list(self):
        # 测试从矩阵列表创建数组方法
        a = self.a
        # 从测试类属性中获取矩阵a
        x = np.array([a, a])
        # 将矩阵a重复两次创建为一个3D数组
        assert_equal(x.shape, [2, 2, 2])
        # 断言x的形状为[2, 2, 2]

    def test_array_to_list(self):
        # 测试从矩阵转换为列表方法
        a = self.a
        # 从测试类属性中获取矩阵a
        assert_equal(a.tolist(), [[1, 2], [3, 4]])
        # 断言矩阵a转换为列表后与期望值[[1, 2], [3, 4]]相等

    def test_fancy_indexing(self):
        # 测试高级索引方法
        a = self.a
        # 从测试类属性中获取矩阵a
        x = a[1, [0, 1, 0]]
        # 使用高级索引获取矩阵a的指定元素组成的子矩阵
        assert_(isinstance(x, matrix))
        # 断言x是matrix类型
        assert_equal(x, matrix([[3,  4,  3]]))
        # 断言x与期望的子矩阵[[3,  4,  3]]相等
        x = a[[1, 0]]
        # 使用高级索引获取矩阵a的指定行组成的子矩阵
        assert_(isinstance(x, matrix))
        # 断言x是matrix类型
        assert_equal(x, matrix([[3,  4], [1, 2]]))
        # 断言x与期望的子矩阵[[3,  4], [1, 2]]相等
        x = a[[[1], [0]], [[1, 0], [0, 1]]]
        # 使用高级索引获取矩阵a的指定元素组成的子矩阵
        assert_(isinstance(x, matrix))
        # 断言x是matrix类型
        assert_equal(x, matrix([[4,  3], [1,  2]]))
        # 断言x与期望的子矩阵[[4,  3], [1,  2]]相等

    def test_matrix_element(self):
        # 测试矩阵元素索引方法
        x = matrix([[1, 2, 3], [4, 5, 6]])
        # 创建一个2x3的矩阵x
        assert_equal(x[0][0], matrix([[1, 2, 3]]))
        # 断言矩阵x的第一个元素是一个1x3的子矩阵
        assert_equal(x[0][0].shape, (1, 3))
        # 断言矩阵x的第一个元素的形状为(1, 3)
        assert_equal(x[0].shape, (1, 3))
        # 断言矩阵x的第一行的形状为(1, 3)
        assert_equal(x[:, 0].shape, (2, 1))
        # 断言矩阵x的第一列的形状为(2, 1)

        x = matrix(0)
        # 创建一个标量值为0的矩阵x
        assert_equal(x[0, 0], 0)
        # 断言矩阵x的第一个元素为0
        assert_equal(x[0], 0)
        # 断言矩阵x的第一行为0
        assert_equal(x[:, 0].shape, x.shape)
        # 断言矩阵x的第一列的形状与矩阵x的形状相同

    def test_scalar_indexing(self):
        # 测试标量索引方法
        x = asmatrix(np.zeros((3, 2), float))
        # 创建一个3x2的零矩阵,并将其转换为矩阵对象
        assert_equal(x[0, 0], x[0][0])
        # 断言矩阵x的两种索引方式得到的第一个元素相等

    def test_row_column_indexing(self):
        # 测试行列索引方法
        x = asmatrix(np.eye(2))
        # 创建一个2x2的单位矩阵,并将其转换为矩阵对象
        assert_array_equal(x[0,:], [[1, 0]])
        # 断言矩阵x的第一行与期望值[[1, 0]]相等
        assert_array_equal(x[1,:], [[0, 1]])
        # 断言矩阵x的第二行与期望值[[0, 1]]相等
        assert_array_equal(x[:, 0], [[1], [0]])
        # 断言矩阵x的第一列与期望值[[1], [0]]相等
        assert_array_equal(x[:, 1], [[0], [1]])
        # 断言矩阵x的第二列与期望值[[0], [1]]相等

    def test_boolean_indexing(self):
        # 测试布尔索引方法
        A = np.arange(6)
        # 创建一个包含0到5的数组A
        A.shape = (3, 2)
        # 将数组A的形状设置为3x2
        x = asmatrix(A)
        # 将数组A转换为矩阵对象x
        assert_array_equal(x[:, np.array([True, False])], x[:, 0])
        # 断言矩阵x使用布尔索引后的结果与矩阵x的第一列相等
        assert_array_equal(x[np.array([True, False, False]),:], x[0,:])
        # 断言矩阵x使用布尔索引后的结果与矩阵x的第一行相等

    def test_list_indexing(self):
        # 测试列表索引方法
        A = np.arange(6)
        # 创建一个包含0到5的数组A
        A.shape = (3, 2)
        # 将数组A的形状设置为3x2
        x = asmatrix(A)
        # 将数组A转换为矩阵对象x
        assert_array_equal(x[:, [1, 0]], x[:, ::-1])
        # 断言矩阵x使用列表索引后的结果与矩阵x逆序列索引的结果相等
        assert_array_equal(x[[2,
    # 测试成员对象的ravel方法:验证数组和矩阵被展平后的形状是否符合预期
    def test_member_ravel(self):
        assert_equal(self.a.ravel().shape, (2,))
        assert_equal(self.m.ravel().shape, (1, 2))

    # 测试成员对象的flatten方法:验证数组和矩阵被展平后的形状是否符合预期
    def test_member_flatten(self):
        assert_equal(self.a.flatten().shape, (2,))
        assert_equal(self.m.flatten().shape, (1, 2))

    # 测试numpy的ravel函数不同参数下的操作:验证数组被展平后的顺序和形状是否符合预期
    def test_numpy_ravel_order(self):
        x = np.array([[1, 2, 3], [4, 5, 6]])
        assert_equal(np.ravel(x), [1, 2, 3, 4, 5, 6])  # 默认顺序展平
        assert_equal(np.ravel(x, order='F'), [1, 4, 2, 5, 3, 6])  # 列优先(Fortran)顺序展平
        assert_equal(np.ravel(x.T), [1, 4, 2, 5, 3, 6])  # 转置后的默认顺序展平
        assert_equal(np.ravel(x.T, order='A'), [1, 2, 3, 4, 5, 6])  # 转置后的自然顺序展平
        x = matrix([[1, 2, 3], [4, 5, 6]])
        assert_equal(np.ravel(x), [1, 2, 3, 4, 5, 6])  # 默认顺序展平
        assert_equal(np.ravel(x, order='F'), [1, 4, 2, 5, 3, 6])  # 列优先(Fortran)顺序展平
        assert_equal(np.ravel(x.T), [1, 4, 2, 5, 3, 6])  # 转置后的默认顺序展平
        assert_equal(np.ravel(x.T, order='A'), [1, 2, 3, 4, 5, 6])  # 转置后的自然顺序展平

    # 测试矩阵对象的ravel方法不同参数下的操作:验证矩阵被展平后的顺序和形状是否符合预期
    def test_matrix_ravel_order(self):
        x = matrix([[1, 2, 3], [4, 5, 6]])
        assert_equal(x.ravel(), [[1, 2, 3, 4, 5, 6]])  # 默认顺序展平
        assert_equal(x.ravel(order='F'), [[1, 4, 2, 5, 3, 6]])  # 列优先(Fortran)顺序展平
        assert_equal(x.T.ravel(), [[1, 4, 2, 5, 3, 6]])  # 转置后的默认顺序展平
        assert_equal(x.T.ravel(order='A'), [[1, 2, 3, 4, 5, 6]])  # 转置后的自然顺序展平

    # 测试数组的内存共享情况:验证数组和其ravel后的对象是否共享内存
    def test_array_memory_sharing(self):
        assert_(np.may_share_memory(self.a, self.a.ravel()))  # 断言数组和其ravel后的对象共享内存
        assert_(not np.may_share_memory(self.a, self.a.flatten()))  # 断言数组和其flatten后的对象不共享内存

    # 测试矩阵的内存共享情况:验证矩阵和其ravel后的对象是否共享内存
    def test_matrix_memory_sharing(self):
        assert_(np.may_share_memory(self.m, self.m.ravel()))  # 断言矩阵和其ravel后的对象共享内存
        assert_(not np.may_share_memory(self.m, self.m.flatten()))  # 断言矩阵和其flatten后的对象不共享内存

    # 测试expand_dims对矩阵的影响:验证当矩阵被转换后,expand_dims是否产生预期的结果
    def test_expand_dims_matrix(self):
        # 矩阵始终是二维的,所以只有在类型从矩阵变化时,expand_dims才有意义。
        a = np.arange(10).reshape((2, 5)).view(np.matrix)
        expanded = np.expand_dims(a, axis=1)
        assert_equal(expanded.ndim, 3)  # 断言扩展后的维度为3
        assert_(not isinstance(expanded, np.matrix))  # 断言扩展后的对象不再是矩阵类型

.\numpy\numpy\matrixlib\tests\test_interaction.py

"""
Tests of interaction of matrix with other parts of numpy.

Note that tests with MaskedArray and linalg are done in separate files.
"""
import pytest  # 导入 pytest 库

import textwrap  # 导入 textwrap 模块,用于格式化文本
import warnings  # 导入 warnings 模块,处理警告信息

import numpy as np  # 导入 NumPy 库,并用 np 别名表示
from numpy.testing import (assert_, assert_equal, assert_raises,
                           assert_raises_regex, assert_array_equal,
                           assert_almost_equal, assert_array_almost_equal)

def test_fancy_indexing():
    # matrix 类型会影响数组的形状。虽然这很奇怪(不使用 getitem 方法,也没有 setitem 方法,也不了解高级索引),
    # 但这里测试的是 gh-3110
    # 2018-04-29: 从 core.tests.test_index 移动到这里。
    m = np.matrix([[1, 2], [3, 4]])

    assert_(isinstance(m[[0, 1, 0], :], np.matrix))

    # gh-3110。注意目前的转置,因为矩阵不正确支持高级索引的维度固定。
    x = np.asmatrix(np.arange(50).reshape(5, 10))
    assert_equal(x[:2, np.array(-1)], x[:2, -1].T)


def test_polynomial_mapdomain():
    # 测试多项式保留矩阵子类型。
    # 2018-04-29: 从 polynomial.tests.polyutils 移动到这里。
    dom1 = [0, 4]
    dom2 = [1, 3]
    x = np.matrix([dom1, dom1])
    res = np.polynomial.polyutils.mapdomain(x, dom1, dom2)
    assert_(isinstance(res, np.matrix))


def test_sort_matrix_none():
    # 2018-04-29: 从 core.tests.test_multiarray 移动到这里。
    a = np.matrix([[2, 1, 0]])
    actual = np.sort(a, axis=None)
    expected = np.matrix([[0, 1, 2]])
    assert_equal(actual, expected)
    assert_(type(expected) is np.matrix)


def test_partition_matrix_none():
    # gh-4301
    # 2018-04-29: 从 core.tests.test_multiarray 移动到这里。
    a = np.matrix([[2, 1, 0]])
    actual = np.partition(a, 1, axis=None)
    expected = np.matrix([[0, 1, 2]])
    assert_equal(actual, expected)
    assert_(type(expected) is np.matrix)


def test_dot_scalar_and_matrix_of_objects():
    # Ticket #2469
    # 2018-04-29: 从 core.tests.test_multiarray 移动到这里。
    arr = np.matrix([1, 2], dtype=object)
    desired = np.matrix([[3, 6]], dtype=object)
    assert_equal(np.dot(arr, 3), desired)
    assert_equal(np.dot(3, arr), desired)


def test_inner_scalar_and_matrix():
    # 2018-04-29: 从 core.tests.test_multiarray 移动到这里。
    for dt in np.typecodes['AllInteger'] + np.typecodes['AllFloat'] + '?':
        sca = np.array(3, dtype=dt)[()]
        arr = np.matrix([[1, 2], [3, 4]], dtype=dt)
        desired = np.matrix([[3, 6], [9, 12]], dtype=dt)
        assert_equal(np.inner(arr, sca), desired)
        assert_equal(np.inner(sca, arr), desired)


def test_inner_scalar_and_matrix_of_objects():
    # Ticket #4482
    # 2018-04-29: 从 core.tests.test_multiarray 移动到这里。
    arr = np.matrix([1, 2], dtype=object)
    desired = np.matrix([[3, 6]], dtype=object)
    assert_equal(np.inner(arr, 3), desired)
    assert_equal(np.inner(3, arr), desired)


def test_iter_allocate_output_subtype():
    pass  # 该测试函数目前没有实现,保留为占位符
    # 确保优先使用具有优先级的子类型
    # 2018-04-29: 从core.tests.test_nditer移动到此处,考虑矩阵特定形状的测试。

    # 创建一个矩阵和一个 ndarray
    a = np.matrix([[1, 2], [3, 4]])
    b = np.arange(4).reshape(2, 2).T
    
    # 使用 np.nditer 迭代器处理 a, b,并且创建一个写入操作数
    i = np.nditer([a, b, None], [],
                  [['readonly'], ['readonly'], ['writeonly', 'allocate']])
    
    # 断言操作数的类型是 np.matrix
    assert_(type(i.operands[2]) is np.matrix)
    
    # 断言操作数的类型不是 np.ndarray
    assert_(type(i.operands[2]) is not np.ndarray)
    
    # 断言操作数的形状是 (2, 2)
    assert_equal(i.operands[2].shape, (2, 2))

    # 对于矩阵,总是希望数据是二维的
    b = np.arange(4).reshape(1, 2, 2)
    
    # 断言在创建 np.nditer 迭代器时会引发 RuntimeError
    assert_raises(RuntimeError, np.nditer, [a, b, None], [],
                  [['readonly'], ['readonly'], ['writeonly', 'allocate']])
    
    # 如果禁用子类型,结果仍然可以工作
    i = np.nditer([a, b, None], [],
                  [['readonly'], ['readonly'],
                   ['writeonly', 'allocate', 'no_subtype']])
    
    # 断言操作数的类型是 np.ndarray
    assert_(type(i.operands[2]) is np.ndarray)
    
    # 断言操作数的类型不是 np.matrix
    assert_(type(i.operands[2]) is not np.matrix)
    
    # 断言操作数的形状是 (1, 2, 2)
    assert_equal(i.operands[2].shape, (1, 2, 2))
# 2018-04-29: moved here from core.tests.test_numeric
def like_function():
    # 创建一个 2x2 的 numpy 矩阵
    a = np.matrix([[1, 2], [3, 4]])
    
    # 遍历 np.zeros_like, np.ones_like, np.empty_like 这三个函数
    for like_function in np.zeros_like, np.ones_like, np.empty_like:
        # 使用当前遍历到的函数 like_function,对矩阵 a 进行操作并返回结果 b
        b = like_function(a)
        # 断言 b 的类型为 np.matrix
        assert_(type(b) is np.matrix)

        # 使用当前遍历到的函数 like_function,以及 subok=False 参数对矩阵 a 进行操作并返回结果 c
        c = like_function(a, subok=False)
        # 断言 c 的类型不是 np.matrix
        assert_(type(c) is not np.matrix)


# 2018-04-29: copied here from core.tests.test_api
def test_array_astype():
    # 创建一个 dtype='f4' 的 2x3 numpy 矩阵 a
    a = np.matrix([[0, 1, 2], [3, 4, 5]], dtype='f4')
    
    # 使用 subok=True 和 copy=False 对矩阵 a 进行数据类型转换,结果赋给 b
    b = a.astype('f4', subok=True, copy=False)
    # 断言 a 和 b 是同一个对象
    assert_(a is b)

    # 使用默认参数 subok=True 对矩阵 a 进行数据类型转换成 'i4',结果赋给 b
    b = a.astype('i4', copy=False)
    # 断言 a 和 b 的值相等
    assert_equal(a, b)
    # 断言 b 的类型是 np.matrix
    assert_equal(type(b), np.matrix)

    # 使用 subok=False 对矩阵 a 进行数据类型转换成 'f4',结果赋给 b
    b = a.astype('f4', subok=False, copy=False)
    # 断言 a 和 b 的值相等
    assert_equal(a, b)
    # 断言 a 和 b 不是同一个对象
    assert_(not (a is b))
    # 断言 b 的类型不是 np.matrix
    assert_(type(b) is not np.matrix)


# 2018-04-29: copied here from core.tests.test_shape_base
def test_stack():
    # 创建一个 2x2 的 numpy 矩阵 m
    m = np.matrix([[1, 2], [3, 4]])
    # 断言在尝试堆叠两个矩阵 m, m 时会引发 ValueError,提示形状过大无法作为矩阵处理
    assert_raises_regex(ValueError, 'shape too large to be a matrix',
                        np.stack, [m, m])


# Tickets #2469 and #4482
# 2018-04-29: moved here from core.tests.test_ufunc
def test_object_scalar_multiply():
    # 创建一个包含对象类型的 numpy 矩阵 arr
    arr = np.matrix([1, 2], dtype=object)
    # 创建一个预期的结果矩阵 desired
    desired = np.matrix([[3, 6]], dtype=object)
    # 断言 np.multiply(arr, 3) 的结果与预期的 desired 相等
    assert_equal(np.multiply(arr, 3), desired)
    # 断言 np.multiply(3, arr) 的结果与预期的 desired 相等
    assert_equal(np.multiply(3, arr), desired)


# Check that it works and that type and
# shape are preserved
# 2018-04-29: moved here from core.tests.test_nanfunctions
def test_nanfunctions_matrices():
    # 创建一个 3x3 的单位矩阵 mat
    mat = np.matrix(np.eye(3))
    
    # 遍历 [np.nanmin, np.nanmax] 这两个函数
    for f in [np.nanmin, np.nanmax]:
        # 对矩阵 mat 沿 axis=0 方向应用函数 f,结果赋给 res
        res = f(mat, axis=0)
        # 断言 res 的类型是 np.matrix
        assert_(isinstance(res, np.matrix))
        # 断言 res 的形状为 (1, 3)
        assert_(res.shape == (1, 3))
        
        # 对矩阵 mat 沿 axis=1 方向应用函数 f,结果赋给 res
        res = f(mat, axis=1)
        # 断言 res 的类型是 np.matrix
        assert_(isinstance(res, np.matrix))
        # 断言 res 的形状为 (3, 1)
        assert_(res.shape == (3, 1))
        
        # 对矩阵 mat 应用函数 f,结果赋给 res
        res = f(mat)
        # 断言 res 是标量
        assert_(np.isscalar(res))
    
    # 检查处理包含 NaN 的行是否正常进行子类化 (#4628)
    mat[1] = np.nan
    # 对于每个函数 `np.nanmin` 和 `np.nanmax` 进行循环处理
    for f in [np.nanmin, np.nanmax]:
        # 捕获警告并记录到 `w` 中
        with warnings.catch_warnings(record=True) as w:
            # 设置警告过滤器为总是显示
            warnings.simplefilter('always')
            # 对矩阵 `mat` 沿着第 0 轴应用函数 `f`
            res = f(mat, axis=0)
            # 断言返回结果是 `np.matrix` 类型
            assert_(isinstance(res, np.matrix))
            # 断言结果中不存在 NaN 值
            assert_(not np.any(np.isnan(res)))
            # 断言警告的数量为 0
            assert_(len(w) == 0)

        # 再次捕获警告并记录到 `w` 中
        with warnings.catch_warnings(record=True) as w:
            # 设置警告过滤器为总是显示
            warnings.simplefilter('always')
            # 对矩阵 `mat` 沿着第 1 轴应用函数 `f`
            res = f(mat, axis=1)
            # 断言返回结果是 `np.matrix` 类型
            assert_(isinstance(res, np.matrix))
            # 断言结果中特定位置存在 NaN 值,其他位置不存在 NaN 值
            assert_(np.isnan(res[1, 0]) and not np.isnan(res[0, 0])
                    and not np.isnan(res[2, 0]))
            # 断言警告的数量为 1,同时验证警告内容为 RuntimeWarning
            assert_(len(w) == 1, 'no warning raised')
            assert_(issubclass(w[0].category, RuntimeWarning))

        # 再次捕获警告并记录到 `w` 中
        with warnings.catch_warnings(record=True) as w:
            # 设置警告过滤器为总是显示
            warnings.simplefilter('always')
            # 对矩阵 `mat` 应用函数 `f`
            res = f(mat)
            # 断言返回结果是标量
            assert_(np.isscalar(res))
            # 断言结果不等于 NaN
            assert_(res != np.nan)
            # 断言警告的数量为 0
            assert_(len(w) == 0)
def test_nanfunctions_matrices_general():
    # 检查函数是否正常工作,并且类型和形状得以保留
    # 2018-04-29: 从core.tests.test_nanfunctions移动到这里

    # 创建一个3x3的单位矩阵
    mat = np.matrix(np.eye(3))

    # 对于每个函数f,分别进行测试:np.nanargmin, np.nanargmax, np.nansum, np.nanprod,
    # np.nanmean, np.nanvar, np.nanstd
    for f in (np.nanargmin, np.nanargmax, np.nansum, np.nanprod,
              np.nanmean, np.nanvar, np.nanstd):
        # 在axis=0上应用函数f
        res = f(mat, axis=0)
        assert_(isinstance(res, np.matrix))
        assert_(res.shape == (1, 3))

        # 在axis=1上应用函数f
        res = f(mat, axis=1)
        assert_(isinstance(res, np.matrix))
        assert_(res.shape == (3, 1))

        # 在整个矩阵上应用函数f
        res = f(mat)
        assert_(np.isscalar(res))

    # 对于函数np.nancumsum和np.nancumprod,同样进行测试
    for f in np.nancumsum, np.nancumprod:
        res = f(mat, axis=0)
        assert_(isinstance(res, np.matrix))
        assert_(res.shape == (3, 3))

        res = f(mat, axis=1)
        assert_(isinstance(res, np.matrix))
        assert_(res.shape == (3, 3))

        res = f(mat)
        assert_(isinstance(res, np.matrix))
        assert_(res.shape == (1, 3*3))


def test_average_matrix():
    # 2018-04-29: 从core.tests.test_function_base移动到这里

    # 创建一个5x5的随机矩阵
    y = np.matrix(np.random.rand(5, 5))

    # 检查平均值函数是否等价
    assert_array_equal(y.mean(0), np.average(y, 0))

    # 创建一个2x2的矩阵a和权重矩阵w
    a = np.matrix([[1, 2], [3, 4]])
    w = np.matrix([[1, 2], [3, 4]])

    # 使用权重计算a的平均值,按axis=0计算
    r = np.average(a, axis=0, weights=w)
    assert_equal(type(r), np.matrix)
    assert_equal(r, [[2.5, 10.0/3]])


def test_dot_matrix():
    # 确保矩阵与ndarray得到相同的结果
    # 2018-04-29: 从core.tests.test_function_base移动到这里

    # 创建一个线性空间数组x和y
    x = np.linspace(0, 5)
    y = np.linspace(-5, 0)

    # 将x和y转换为矩阵类型
    mx = np.matrix(x)
    my = np.matrix(y)

    # 计算x和y的点积
    r = np.dot(x, y)

    # 计算矩阵mx和my的点积
    mr = np.dot(mx, my.T)
    assert_almost_equal(mr, r)


def test_ediff1d_matrix():
    # 2018-04-29: 从core.tests.test_arraysetops移动到这里

    # 确保np.ediff1d返回类型为矩阵
    assert(isinstance(np.ediff1d(np.matrix(1)), np.matrix))
    assert(isinstance(np.ediff1d(np.matrix(1), to_begin=1), np.matrix))


def test_apply_along_axis_matrix():
    # 此测试对矩阵特别恶毒,因为矩阵拒绝成为1维
    # 2018-04-29: 从core.tests.test_shape_base移动到这里

    # 定义一个函数,将每行翻倍
    def double(row):
        return row * 2

    # 创建一个2x2的矩阵m和预期的结果矩阵expected
    m = np.matrix([[0, 1], [2, 3]])
    expected = np.matrix([[0, 2], [4, 6]])

    # 沿着axis=0应用函数double
    result = np.apply_along_axis(double, 0, m)
    assert_(isinstance(result, np.matrix))
    assert_array_equal(result, expected)

    # 沿着axis=1应用函数double
    result = np.apply_along_axis(double, 1, m)
    assert_(isinstance(result, np.matrix))
    assert_array_equal(result, expected)


def test_kron_matrix():
    # 2018-04-29: 从core.tests.test_shape_base移动到这里

    # 创建一个2x2的全1矩阵a,并将其转换为矩阵类型m
    a = np.ones([2, 2])
    m = np.asmatrix(a)

    # 检查np.kron函数返回类型的一致性
    assert_equal(type(np.kron(a, a)), np.ndarray)
    assert_equal(type(np.kron(m, m)), np.matrix)
    assert_equal(type(np.kron(a, m)), np.matrix)
    assert_equal(type(np.kron(m, a)), np.matrix)


class TestConcatenatorMatrix:
    # 2018-04-29: 从core.tests.test_index_tricks移动到这里
    # 定义一个测试方法,用于测试 np.r_ 方法的不同用法和结果
    def test_matrix(self):
        # 创建两个简单的数组
        a = [1, 2]
        b = [3, 4]

        # 使用 np.r_ 方法按行连接数组 a 和 b,生成一个行向量
        ab_r = np.r_['r', a, b]
        # 使用 np.r_ 方法按列连接数组 a 和 b,生成一个列向量
        ab_c = np.r_['c', a, b]

        # 断言 ab_r 和 ab_c 的类型为 np.matrix
        assert_equal(type(ab_r), np.matrix)
        assert_equal(type(ab_c), np.matrix)

        # 断言生成的行向量 ab_r 转换为数组后的值为 [[1, 2, 3, 4]]
        assert_equal(np.array(ab_r), [[1, 2, 3, 4]])
        # 断言生成的列向量 ab_c 转换为数组后的值为 [[1], [2], [3], [4]]
        assert_equal(np.array(ab_c), [[1], [2], [3], [4]])

        # 测试使用不支持的连接类型 'rc' 时是否会引发 ValueError 异常
        assert_raises(ValueError, lambda: np.r_['rc', a, b])

    # 定义一个测试方法,用于测试 np.r_ 方法在包含标量的情况下的行连接
    def test_matrix_scalar(self):
        # 使用 np.r_ 方法将包含标量的数组 [1, 2] 和标量 3 进行行连接
        r = np.r_['r', [1, 2], 3]
        # 断言连接结果的类型为 np.matrix
        assert_equal(type(r), np.matrix)
        # 断言连接结果转换为数组后的值为 [[1, 2, 3]]
        assert_equal(np.array(r), [[1, 2, 3]])

    # 定义一个测试方法,用于测试 np.r_ 方法在使用字符串建造器时的结果
    def test_matrix_builder(self):
        # 创建四个简单的数组
        a = np.array([1])
        b = np.array([2])
        c = np.array([3])
        d = np.array([4])

        # 使用字符串建造器 'a, b; c, d' 创建一个 2x2 的矩阵
        actual = np.r_['a, b; c, d']
        # 使用 np.bmat 方法生成一个与 actual 相同的期望矩阵
        expected = np.bmat([[a, b], [c, d]])

        # 断言 actual 和 expected 的值相等
        assert_equal(actual, expected)
        # 断言 actual 和 expected 的类型相同
        assert_equal(type(actual), type(expected))
# 2018-04-29: 从 testing.tests.test_utils 移动到此处。
def test_array_equal_error_message_matrix():
    # 使用 pytest.raises 来捕获 AssertionError 异常,存储异常信息到 exc_info
    with pytest.raises(AssertionError) as exc_info:
        # 断言 np.array([1, 2]) 与 np.matrix([1, 2]) 相等,预期会引发 AssertionError
        assert_equal(np.array([1, 2]), np.matrix([1, 2]))
    # 将异常信息转换为字符串
    msg = str(exc_info.value)
    # 预期的错误信息参考,去除首尾空白和缩进
    msg_reference = textwrap.dedent("""\
    
    Arrays are not equal

    (shapes (2,), (1, 2) mismatch)
     ACTUAL: array([1, 2])
     DESIRED: matrix([[1, 2]])""")
    # 断言捕获的异常信息与预期的错误信息相等
    assert_equal(msg, msg_reference)


def test_array_almost_equal_matrix():
    # 矩阵切片保持二维,而数组不一定。参见 gh-8452。
    # 2018-04-29: 从 testing.tests.test_utils 移动到此处。
    # 创建几个不同的 np.matrix 示例
    m1 = np.matrix([[1., 2.]])
    m2 = np.matrix([[1., np.nan]])
    m3 = np.matrix([[1., -np.inf]])
    m4 = np.matrix([[np.nan, np.inf]])
    m5 = np.matrix([[1., 2.], [np.nan, np.inf]])
    # 对于 assert_array_almost_equal 和 assert_almost_equal 两个函数进行迭代
    for assert_func in assert_array_almost_equal, assert_almost_equal:
        # 对每个矩阵 m 进行测试
        for m in m1, m2, m3, m4, m5:
            # 断言矩阵 m 与自身的近似相等性
            assert_func(m, m)
            # 将矩阵 m 转换为数组 a,并断言数组 a 与矩阵 m 的近似相等性
            a = np.array(m)
            assert_func(a, m)
            # 断言矩阵 m 与数组 a 的近似相等性
            assert_func(m, a)

.\numpy\numpy\matrixlib\tests\test_masked_matrix.py

import pickle  # 导入 pickle 库,用于对象的序列化和反序列化

import numpy as np  # 导入 NumPy 库,进行科学计算
from numpy.testing import assert_warns  # 导入 NumPy 测试模块中的 assert_warns 函数
from numpy.ma.testutils import (assert_, assert_equal, assert_raises,
                                assert_array_equal)  # 导入 NumPy 测试工具中的断言函数
from numpy.ma.core import (masked_array, masked_values, masked, allequal,
                           MaskType, getmask, MaskedArray, nomask,
                           log, add, hypot, divide)  # 导入 NumPy 掩码数组相关的函数和类
from numpy.ma.extras import mr_  # 导入 NumPy 掩码数组额外的函数


class MMatrix(MaskedArray, np.matrix,):  # 定义 MMatrix 类,继承自 MaskedArray 和 np.matrix

    def __new__(cls, data, mask=nomask):
        mat = np.matrix(data)  # 将输入数据转换为 np.matrix 对象
        _data = MaskedArray.__new__(cls, data=mat, mask=mask)  # 创建 MaskedArray 对象
        return _data

    def __array_finalize__(self, obj):
        np.matrix.__array_finalize__(self, obj)  # 在创建后处理 np.matrix 对象
        MaskedArray.__array_finalize__(self, obj)  # 在创建后处理 MaskedArray 对象
        return

    @property
    def _series(self):
        _view = self.view(MaskedArray)  # 创建一个 MaskedArray 的视图
        _view._sharedmask = False  # 设置共享掩码为 False
        return _view  # 返回视图对象


class TestMaskedMatrix:
    def test_matrix_indexing(self):
        # Tests conversions and indexing
        x1 = np.matrix([[1, 2, 3], [4, 3, 2]])  # 创建一个 np.matrix 对象
        x2 = masked_array(x1, mask=[[1, 0, 0], [0, 1, 0]])  # 创建一个掩码数组对象 x2
        x3 = masked_array(x1, mask=[[0, 1, 0], [1, 0, 0]])  # 创建一个掩码数组对象 x3
        x4 = masked_array(x1)  # 创建一个掩码数组对象 x4
        # test conversion to strings
        str(x2)  # 转换为字符串,可能会引发异常
        repr(x2)  # 返回对象的字符串表示,可能会引发异常
        # tests of indexing
        assert_(type(x2[1, 0]) is type(x1[1, 0]))  # 断言 x2 和 x1 在指定位置上的类型相同
        assert_(x1[1, 0] == x2[1, 0])  # 断言 x1 和 x2 在指定位置上的值相等
        assert_(x2[1, 1] is masked)  # 断言 x2 在指定位置上是否是掩码
        assert_equal(x1[0, 2], x2[0, 2])  # 断言 x1 和 x2 在指定位置上的值相等
        assert_equal(x1[0, 1:], x2[0, 1:])  # 断言 x1 和 x2 在指定范围上的值相等
        assert_equal(x1[:, 2], x2[:, 2])  # 断言 x1 和 x2 在指定列上的值相等
        assert_equal(x1[:], x2[:])  # 断言 x1 和 x2 的值相等
        assert_equal(x1[1:], x3[1:])  # 断言 x1 和 x3 在指定范围上的值相等
        x1[0, 2] = 9  # 修改 x1 的值
        x2[0, 2] = 9  # 修改 x2 的值
        assert_equal(x1, x2)  # 断言 x1 和 x2 的值相等
        x1[0, 1:] = 99  # 修改 x1 的值
        x2[0, 1:] = 99  # 修改 x2 的值
        assert_equal(x1, x2)  # 断言 x1 和 x2 的值相等
        x2[0, 1] = masked  # 在 x2 中指定位置设置为掩码
        assert_equal(x1, x2)  # 断言 x1 和 x2 的值相等
        x2[0, 1:] = masked  # 在 x2 中指定范围设置为掩码
        assert_equal(x1, x2)  # 断言 x1 和 x2 的值相等
        x2[0, :] = x1[0, :]  # 修改 x2 的部分值
        x2[0, 1] = masked  # 在 x2 中指定位置设置为掩码
        assert_(allequal(getmask(x2), np.array([[0, 1, 0], [0, 1, 0]])))  # 断言 x2 的掩码是否与指定数组相等
        x3[1, :] = masked_array([1, 2, 3], [1, 1, 0])  # 修改 x3 的部分值
        assert_(allequal(getmask(x3)[1], masked_array([1, 1, 0])))  # 断言 x3 的掩码是否与指定数组相等
        assert_(allequal(getmask(x3[1]), masked_array([1, 1, 0])))  # 断言 x3 的掩码是否与指定数组相等
        x4[1, :] = masked_array([1, 2, 3], [1, 1, 0])  # 修改 x4 的部分值
        assert_(allequal(getmask(x4[1]), masked_array([1, 1, 0])))  # 断言 x4 的掩码是否与指定数组相等
        assert_(allequal(x4[1], masked_array([1, 2, 3])))  # 断言 x4 在指定位置上的值是否与指定数组相等
        x1 = np.matrix(np.arange(5) * 1.0)  # 创建一个新的 np.matrix 对象
        x2 = masked_values(x1, 3.0)  # 使用指定值创建掩码数组对象
        assert_equal(x1, x2)  # 断言 x1 和 x2 的值相等
        assert_(allequal(masked_array([0, 0, 0, 1, 0], dtype=MaskType),
                         x2.mask))  # 断言 x2 的掩码是否与指定数组相等
        assert_equal(3.0, x2.fill_value)  # 断言 x2 的填充值是否等于指定值
    # 定义一个测试方法,用于测试带有子类 ndarray 的序列化
    def test_pickling_subbaseclass(self):
        # 创建一个带有掩码的 masked_array 对象,其中包含一个 10 个元素的矩阵
        a = masked_array(np.matrix(list(range(10))), mask=[1, 0, 1, 0, 0] * 2)
        # 对不同协议版本进行循环测试序列化和反序列化操作
        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
            # 序列化对象 a,并使用指定的协议版本进行反序列化
            a_pickled = pickle.loads(pickle.dumps(a, protocol=proto))
            # 断言反序列化后的对象的掩码与原始对象的掩码相同
            assert_equal(a_pickled._mask, a._mask)
            # 断言反序列化后的对象与原始对象相等
            assert_equal(a_pickled, a)
            # 断言反序列化后的对象的 _data 属性是一个 np.matrix 类型的对象
            assert_(isinstance(a_pickled._data, np.matrix))

    # 定义一个测试方法,测试带有矩阵的 masked_array 对象的计数和平均值计算
    def test_count_mean_with_matrix(self):
        # 创建一个带有矩阵和全零掩码的 masked_array 对象
        m = masked_array(np.matrix([[1, 2], [3, 4]]), mask=np.zeros((2, 2)))

        # 断言沿着 axis=0 方向计数的结果形状为 (1, 2)
        assert_equal(m.count(axis=0).shape, (1, 2))
        # 断言沿着 axis=1 方向计数的结果形状为 (2, 1)
        assert_equal(m.count(axis=1).shape, (2, 1))

        # 确保在 mean 和 var 方法内部进行广播计算正常工作
        assert_equal(m.mean(axis=0), [[2., 3.]])
        assert_equal(m.mean(axis=1), [[1.5], [3.5]])

    # 定义一个测试方法,测试 flat 属性在矩阵中的使用情况
    def test_flat(self):
        # 创建一个带有矩阵和部分掩码的 masked_array 对象,用于测试 flat 属性
        test = masked_array(np.matrix([[1, 2, 3]]), mask=[0, 0, 1])
        # 断言通过 flat 访问第二个元素返回正确的值 2
        assert_equal(test.flat[1], 2)
        # 断言通过 flat 访问第三个元素返回 masked
        assert_equal(test.flat[2], masked)
        # 断言通过 flat 访问切片 [0:2] 返回与指定范围的元素相等的结果
        assert_(np.all(test.flat[0:2] == test[0, 0:2]))

        # 创建另一个带有矩阵和部分掩码的 masked_array 对象,并修改其 flat 属性
        test = masked_array(np.matrix([[1, 2, 3]]), mask=[0, 0, 1])
        test.flat = masked_array([3, 2, 1], mask=[1, 0, 0])
        # 创建一个作为对照的 masked_array 对象
        control = masked_array(np.matrix([[3, 2, 1]]), mask=[1, 0, 0])
        # 断言修改 flat 属性后的对象与对照对象相等
        assert_equal(test, control)

        # 再次创建带有矩阵和部分掩码的 masked_array 对象,测试 flat 属性的设置
        test = masked_array(np.matrix([[1, 2, 3]]), mask=[0, 0, 1])
        # 获取 flat 属性的引用
        testflat = test.flat
        # 使用切片操作修改 flat 属性的值,使其与 control 对象相等
        testflat[:] = testflat[[2, 1, 0]]
        # 断言修改后的对象与对照对象相等
        assert_equal(test, control)

        # 对 flat 属性的单独元素进行修改测试
        testflat[0] = 9
        # 断言修改后的对象与 control 对象依然相等
        # 测试矩阵保持正确的形状(#4615)
        a = masked_array(np.matrix(np.eye(2)), mask=0)
        b = a.flat
        b01 = b[:2]
        # 断言修改后的对象数据与预期值相等
        assert_equal(b01.data, np.array([[1., 0.]]))
        # 断言修改后的对象掩码与预期值相等
        assert_equal(b01.mask, np.array([[False, False]]))
    def test_allany_onmatrices(self):
        # 创建一个 NumPy 数组 x
        x = np.array([[0.13, 0.26, 0.90],
                      [0.28, 0.33, 0.63],
                      [0.31, 0.87, 0.70]])
        # 将数组 x 转换为 NumPy 矩阵 X
        X = np.matrix(x)
        # 创建一个布尔类型的 NumPy 数组 m
        m = np.array([[True, False, False],
                      [False, False, False],
                      [True, True, False]], dtype=np.bool)
        # 使用 m 创建一个 MaskedArray 对象 mX
        mX = masked_array(X, mask=m)
        # 创建两个布尔类型的 MaskedArray 对象 mXbig 和 mXsmall
        mXbig = (mX > 0.5)
        mXsmall = (mX < 0.5)

        # 断言:mXbig 中不是所有元素都大于 0.5
        assert_(not mXbig.all())
        # 断言:mXbig 中至少有一个元素大于 0.5
        assert_(mXbig.any())
        # 断言:mXbig 沿着列的维度上所有元素都大于 0.5
        assert_equal(mXbig.all(0), np.matrix([False, False, True]))
        # 断言:mXbig 沿着行的维度上所有元素都大于 0.5
        assert_equal(mXbig.all(1), np.matrix([False, False, True]).T)
        # 断言:mXbig 沿着列的维度上至少有一个元素大于 0.5
        assert_equal(mXbig.any(0), np.matrix([False, False, True]))
        # 断言:mXbig 沿着行的维度上至少有一个元素大于 0.5
        assert_equal(mXbig.any(1), np.matrix([True, True, True]).T)

        # 断言:mXsmall 中不是所有元素都小于 0.5
        assert_(not mXsmall.all())
        # 断言:mXsmall 中至少有一个元素小于 0.5
        assert_(mXsmall.any())
        # 断言:mXsmall 沿着列的维度上所有元素都小于 0.5
        assert_equal(mXsmall.all(0), np.matrix([True, True, False]))
        # 断言:mXsmall 沿着行的维度上所有元素都小于 0.5
        assert_equal(mXsmall.all(1), np.matrix([False, False, False]).T)
        # 断言:mXsmall 沿着列的维度上至少有一个元素小于 0.5
        assert_equal(mXsmall.any(0), np.matrix([True, True, False]))
        # 断言:mXsmall 沿着行的维度上至少有一个元素小于 0.5
        assert_equal(mXsmall.any(1), np.matrix([True, True, False]).T)

    def test_compressed(self):
        # 创建一个 NumPy 矩阵 a,并为其创建一个 MaskedArray 对象 b
        a = masked_array(np.matrix([1, 2, 3, 4]), mask=[0, 0, 0, 0])
        # 使用 compressed 方法压缩 MaskedArray 对象 a,得到 b
        b = a.compressed()
        # 断言:压缩后的 b 应当与原始的 a 相等
        assert_equal(b, a)
        # 断言:b 应当是一个 NumPy 矩阵
        assert_(isinstance(b, np.matrix))
        # 修改 a 中的一个元素为 masked,并重新压缩得到 b
        a[0, 0] = masked
        b = a.compressed()
        # 断言:压缩后的 b 应当是 [[2, 3, 4]]
        assert_equal(b, [[2, 3, 4]])

    def test_ravel(self):
        # 创建一个 NumPy 矩阵 a,并为其创建一个 MaskedArray 对象 aravel
        a = masked_array(np.matrix([1, 2, 3, 4, 5]), mask=[[0, 1, 0, 0, 0]])
        aravel = a.ravel()
        # 断言:aravel 应当是一个形状为 (1, 5) 的矩阵
        assert_equal(aravel.shape, (1, 5))
        # 断言:aravel 的掩码应当与 a 的形状相同
        assert_equal(aravel._mask.shape, a.shape)

    def test_view(self):
        # 测试带有灵活数据类型的视图功能
        iterator = list(zip(np.arange(10), np.random.rand(10)))
        data = np.array(iterator)
        # 创建一个 MaskedArray 对象 a,使用自定义的数据类型 [('a', float), ('b', float)] 
        a = masked_array(iterator, dtype=[('a', float), ('b', float)])
        # 将 a 的第一个元素的掩码设置为 (1, 0)
        a.mask[0] = (1, 0)
        # 使用 view 方法创建一个新的 NumPy 矩阵 test
        test = a.view((float, 2), np.matrix)
        # 断言:test 应当与原始数据 data 相等
        assert_equal(test, data)
        # 断言:test 应当是一个 NumPy 矩阵
        assert_(isinstance(test, np.matrix))
        # 断言:test 不是一个 MaskedArray 对象
        assert_(not isinstance(test, MaskedArray))
class TestSubclassing:
    # Test suite for masked subclasses of ndarray.

    def setup_method(self):
        # 创建一个长度为5的浮点数 ndarray
        x = np.arange(5, dtype='float')
        # 使用 MMatrix 类型创建一个带有掩码的 ndarray
        mx = MMatrix(x, mask=[0, 1, 0, 0, 0])
        # 将 x 和 mx 存储到实例变量 self.data 中
        self.data = (x, mx)

    def test_maskedarray_subclassing(self):
        # Tests subclassing MaskedArray
        (x, mx) = self.data
        # 检查 mx._data 是否为 np.matrix 类型
        assert_(isinstance(mx._data, np.matrix))

    def test_masked_unary_operations(self):
        # Tests masked_unary_operation
        (x, mx) = self.data
        # 在忽略除法时进行操作
        with np.errstate(divide='ignore'):
            # 检查 log(mx) 是否为 MMatrix 类型
            assert_(isinstance(log(mx), MMatrix))
            # 检查 log(x) 是否与 np.log(x) 相等
            assert_equal(log(x), np.log(x))

    def test_masked_binary_operations(self):
        # Tests masked_binary_operation
        (x, mx) = self.data
        # 结果应为 MMatrix 类型
        assert_(isinstance(add(mx, mx), MMatrix))
        assert_(isinstance(add(mx, x), MMatrix))
        # 检查 add(mx, x) 是否等于 mx+x
        assert_equal(add(mx, x), mx+x)
        # 检查 add(mx, mx)._data 是否为 np.matrix 类型
        assert_(isinstance(add(mx, mx)._data, np.matrix))
        # 检查 add.outer(mx, mx) 是否为 MMatrix 类型,并发出 DeprecationWarning
        with assert_warns(DeprecationWarning):
            assert_(isinstance(add.outer(mx, mx), MMatrix))
        # 检查 hypot(mx, mx) 和 hypot(mx, x) 是否为 MMatrix 类型
        assert_(isinstance(hypot(mx, mx), MMatrix))
        assert_(isinstance(hypot(mx, x), MMatrix))

    def test_masked_binary_operations2(self):
        # Tests domained_masked_binary_operation
        (x, mx) = self.data
        # 使用 mx.data 创建一个带有掩码的 masked_array 对象
        xmx = masked_array(mx.data.__array__(), mask=mx.mask)
        # 检查 divide(mx, mx) 和 divide(mx, x) 是否为 MMatrix 类型
        assert_(isinstance(divide(mx, mx), MMatrix))
        assert_(isinstance(divide(mx, x), MMatrix))
        # 检查 divide(mx, mx) 和 divide(xmx, xmx) 是否相等
        assert_equal(divide(mx, mx), divide(xmx, xmx))

class TestConcatenator:
    # Tests for mr_, the equivalent of r_ for masked arrays.

    def test_matrix_builder(self):
        # 测试 mr_['1, 2; 3, 4'] 是否引发 np.ma.MAError 异常
        assert_raises(np.ma.MAError, lambda: mr_['1, 2; 3, 4'])

    def test_matrix(self):
        # Test consistency with unmasked version.  If we ever deprecate
        # matrix, this test should either still pass, or both actual and
        # expected should fail to be build.
        # 检查 mr_['r', 1, 2, 3] 是否与预期的 np.ma.array(np.r_['r', 1, 2, 3]) 一致
        actual = mr_['r', 1, 2, 3]
        expected = np.ma.array(np.r_['r', 1, 2, 3])
        assert_array_equal(actual, expected)

        # outer type is masked array, inner type is matrix
        # 检查 actual 和 expected 的类型是否一致,并且它们的数据类型也一致
        assert_equal(type(actual), type(expected))
        assert_equal(type(actual.data), type(expected.data))

.\numpy\numpy\matrixlib\tests\test_matrix_linalg.py

# 导入 NumPy 库并起一个别名 np
import numpy as np

# 从 NumPy 的线性代数测试模块中导入所需的测试用例和辅助函数
from numpy.linalg.tests.test_linalg import (
    LinalgCase, apply_tag, TestQR as _TestQR, LinalgTestCase,
    _TestNorm2D, _TestNormDoubleBase, _TestNormSingleBase, _TestNormInt64Base,
    SolveCases, InvCases, EigvalsCases, EigCases, SVDCases, CondCases,
    PinvCases, DetCases, LstsqCases)

# 定义一个空列表用于存放测试用例
CASES = []

# 添加 "square" 标签的测试用例到 CASES 列表中
CASES += apply_tag('square', [
    # 测试用例:0x0 矩阵,空的双精度浮点型矩阵视图
    LinalgCase("0x0_matrix",
               np.empty((0, 0), dtype=np.double).view(np.matrix),
               np.empty((0, 1), dtype=np.double).view(np.matrix),
               tags={'size-0'}),
    # 测试用例:仅有矩阵 b
    LinalgCase("matrix_b_only",
               np.array([[1., 2.], [3., 4.]]),
               np.matrix([2., 1.]).T),
    # 测试用例:同时包含矩阵 a 和 b
    LinalgCase("matrix_a_and_b",
               np.matrix([[1., 2.], [3., 4.]]),
               np.matrix([2., 1.]).T),
])

# 添加 "hermitian" 标签的测试用例到 CASES 列表中
CASES += apply_tag('hermitian', [
    # 测试用例:对称矩阵,包含矩阵 a 和 b
    LinalgCase("hmatrix_a_and_b",
               np.matrix([[1., 2.], [2., 1.]]),
               None),
])

# 定义一个测试用例类 MatrixTestCase,继承自 LinalgTestCase,用于统一管理所有测试用例
class MatrixTestCase(LinalgTestCase):
    TEST_CASES = CASES

# 下面是各种具体的测试类,每个类都继承自 MatrixTestCase 并实现特定的测试功能

# 求解矩阵的测试类
class TestSolveMatrix(SolveCases, MatrixTestCase):
    pass

# 求逆矩阵的测试类
class TestInvMatrix(InvCases, MatrixTestCase):
    pass

# 求特征值的测试类
class TestEigvalsMatrix(EigvalsCases, MatrixTestCase):
    pass

# 求特征向量的测试类
class TestEigMatrix(EigCases, MatrixTestCase):
    pass

# 奇异值分解的测试类
class TestSVDMatrix(SVDCases, MatrixTestCase):
    pass

# 矩阵条件数的测试类
class TestCondMatrix(CondCases, MatrixTestCase):
    pass

# 伪逆矩阵的测试类
class TestPinvMatrix(PinvCases, MatrixTestCase):
    pass

# 行列式的测试类
class TestDetMatrix(DetCases, MatrixTestCase):
    pass

# 最小二乘解的测试类
class TestLstsqMatrix(LstsqCases, MatrixTestCase):
    pass

# 二维范数的测试类,使用 np.matrix 作为数组类型
class _TestNorm2DMatrix(_TestNorm2D):
    array = np.matrix

# 双精度范数的测试类,继承自 _TestNorm2DMatrix 和 _TestNormDoubleBase
class TestNormDoubleMatrix(_TestNorm2DMatrix, _TestNormDoubleBase):
    pass

# 单精度范数的测试类,继承自 _TestNorm2DMatrix 和 _TestNormSingleBase
class TestNormSingleMatrix(_TestNorm2DMatrix, _TestNormSingleBase):
    pass

# Int64 范数的测试类,继承自 _TestNorm2DMatrix 和 _TestNormInt64Base
class TestNormInt64Matrix(_TestNorm2DMatrix, _TestNormInt64Base):
    pass

# QR 分解的测试类,使用 np.matrix 作为数组类型
class TestQRMatrix(_TestQR):
    array = np.matrix

.\numpy\numpy\matrixlib\tests\test_multiarray.py

import numpy as np  # 导入 NumPy 库
from numpy.testing import assert_, assert_equal, assert_array_equal  # 导入测试工具函数

class TestView:
    def test_type(self):
        x = np.array([1, 2, 3])  # 创建一个 NumPy 数组
        assert_(isinstance(x.view(np.matrix), np.matrix))  # 断言转换为矩阵类型后的类型判断

    def test_keywords(self):
        x = np.array([(1, 2)], dtype=[('a', np.int8), ('b', np.int8)])  # 创建一个结构化数组
        # 我们必须在这里明确指定字节顺序:
        y = x.view(dtype='<i2', type=np.matrix)  # 将数组视图转换为指定类型(矩阵),指定小端序
        assert_array_equal(y, [[513]])  # 断言视图转换后的数组内容

        assert_(isinstance(y, np.matrix))  # 断言 y 是 np.matrix 类型
        assert_equal(y.dtype, np.dtype('<i2'))  # 断言 y 的数据类型为小端序的 16 位整数

.\numpy\numpy\matrixlib\tests\test_numeric.py

import numpy as np                              # 导入NumPy库,用于科学计算
from numpy.testing import assert_equal          # 从NumPy的测试模块导入断言函数assert_equal,用于比较测试结果

class TestDot:
    def test_matscalar(self):
        b1 = np.matrix(np.ones((3, 3), dtype=complex))  # 创建一个3x3的复数矩阵,元素值为1
        assert_equal(b1*1.0, b1)                        # 断言:矩阵b1乘以1.0应该等于原始矩阵b1本身

def test_diagonal():
    b1 = np.matrix([[1,2],[3,4]])               # 创建一个2x2的NumPy矩阵b1
    diag_b1 = np.matrix([[1, 4]])              # 创建一个1x2的矩阵diag_b1,表示b1的对角线元素
    array_b1 = np.array([1, 4])                 # 创建一个NumPy数组array_b1,表示b1的对角线元素

    assert_equal(b1.diagonal(), diag_b1)        # 断言:b1对象的对角线元素应该与diag_b1矩阵相等
    assert_equal(np.diagonal(b1), array_b1)     # 断言:b1矩阵的对角线元素应该与array_b1数组相等
    assert_equal(np.diag(b1), array_b1)         # 断言:使用np.diag()函数提取b1矩阵的对角线元素,应该与array_b1数组相等

.\numpy\numpy\matrixlib\tests\test_regression.py

import numpy as np  # 导入NumPy库,用于数值计算
from numpy.testing import assert_, assert_equal, assert_raises  # 导入NumPy测试模块的断言方法

class TestRegression:
    def test_kron_matrix(self):
        # Ticket #71
        x = np.matrix('[1 0; 1 0]')  # 创建一个2x2的矩阵对象x
        assert_equal(type(np.kron(x, x)), type(x))  # 断言np.kron(x, x)的类型与x相同

    def test_matrix_properties(self):
        # Ticket #125
        a = np.matrix([1.0], dtype=float)  # 创建一个浮点数矩阵a,包含单个元素1.0
        assert_(type(a.real) is np.matrix)  # 断言a的实部的类型为np.matrix
        assert_(type(a.imag) is np.matrix)  # 断言a的虚部的类型为np.matrix
        c, d = np.matrix([0.0]).nonzero()  # 获取矩阵[0.0]的非零元素索引,分别赋值给c和d
        assert_(type(c) is np.ndarray)  # 断言c的类型为np.ndarray
        assert_(type(d) is np.ndarray)  # 断言d的类型为np.ndarray

    def test_matrix_multiply_by_1d_vector(self):
        # Ticket #473
        def mul():
            np.asmatrix(np.eye(2))*np.ones(2)  # 对单位矩阵np.eye(2)乘以全1向量np.ones(2)

        assert_raises(ValueError, mul)  # 断言mul函数会引发ValueError异常

    def test_matrix_std_argmax(self):
        # Ticket #83
        x = np.asmatrix(np.random.uniform(0, 1, (3, 3)))  # 创建一个3x3的随机浮点数矩阵x
        assert_equal(x.std().shape, ())  # 断言x的标准差的形状为标量
        assert_equal(x.argmax().shape, ())  # 断言x的最大值索引的形状为标量

.\numpy\numpy\matrixlib\tests\__init__.py

# 定义一个名为 `merge_sort` 的函数,用于执行归并排序算法
def merge_sort(arr):
    # 如果输入数组长度小于等于1,则直接返回数组本身,无需排序
    if len(arr) <= 1:
        return arr
    
    # 计算数组中间位置
    mid = len(arr) // 2
    
    # 递归调用 `merge_sort` 函数,对数组左半部分进行排序
    left_half = merge_sort(arr[:mid])
    # 递归调用 `merge_sort` 函数,对数组右半部分进行排序
    right_half = merge_sort(arr[mid:])
    
    # 返回左右两半部分合并后的结果
    return merge(left_half, right_half)

# 定义一个名为 `merge` 的函数,用于合并两个已排序的数组
def merge(left, right):
    # 初始化一个空数组 `result` 用于存放合并后的结果
    result = []
    # 初始化两个指针 `i` 和 `j`,分别指向左右两个数组的起始位置
    i = j = 0
    
    # 当左右两个数组都还有元素未处理时,执行循环
    while i < len(left) and j < len(right):
        # 比较左右两个数组当前位置的元素,将较小的元素加入 `result` 数组
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    
    # 将左右剩余的元素加入 `result` 数组(其中一个数组可能还有剩余元素)
    result.extend(left[i:])
    result.extend(right[j:])
    
    # 返回合并后的结果数组 `result`
    return result

.\numpy\numpy\matrixlib\__init__.py

"""Sub-package containing the matrix class and related functions.

"""
# 从当前包中导入 defmatrix 模块
from . import defmatrix
# 从 defmatrix 模块中导入所有公开的符号
from .defmatrix import *
# 将 defmatrix 模块中所有公开的符号添加到当前模块的 __all__ 列表中
__all__ = defmatrix.__all__

# 从 numpy._pytesttester 模块中导入 PytestTester 类
from numpy._pytesttester import PytestTester
# 创建一个 PytestTester 类的实例 test,并指定其名称为当前模块的名称
test = PytestTester(__name__)
# 删除当前作用域中的 PytestTester 类的引用,避免全局污染
del PytestTester

.\numpy\numpy\matrixlib\__init__.pyi

# 从 numpy._pytesttester 模块中导入 PytestTester 类
from numpy._pytesttester import PytestTester

# 从 numpy 模块中导入 matrix 类并将其命名为 matrix
from numpy import (
    matrix as matrix,
)

# 从 numpy.matrixlib.defmatrix 模块中导入 bmat, mat, asmatrix 三个函数
from numpy.matrixlib.defmatrix import (
    bmat as bmat,
    mat as mat,
    asmatrix as asmatrix,
)

# 定义 __all__ 变量,表明模块中公开的所有符号,其类型为字符串列表
__all__: list[str]

# 定义 test 变量,类型为 PytestTester 类,用于执行 numpy 模块的测试
test: PytestTester

.\numpy\numpy\polynomial\chebyshev.py

# 将切比雪夫级数转换为 z 级数的函数
def _cseries_to_zseries(c):
    """Convert Chebyshev series to z-series.

    Convert a Chebyshev series to the equivalent z-series. The result is
    obtained by applying the algebraic identity involving z, transforming
    the Chebyshev series coefficients to their corresponding z-series
    coefficients.
    """
    # 返回转换后的 z 级数系数
    return (c + np.flip(c)) / 2
    # 计算输入 Chebyshev 系数数组的大小
    n = c.size
    # 创建一个全零数组,长度为 2*n-1,数据类型与输入数组 c 相同
    zs = np.zeros(2*n-1, dtype=c.dtype)
    # 将 Chebyshev 系数数组 c 的一半赋值给 zs 数组的后半部分
    zs[n-1:] = c/2
    # 返回 zs 数组与其反转数组的元素对应相加的结果
    return zs + zs[::-1]
def _zseries_to_cseries(zs):
    """Convert z-series to a Chebyshev series.

    Convert a z series to the equivalent Chebyshev series. The result is
    never an empty array. The dtype of the return is the same as that of
    the input. No checks are run on the arguments as this routine is for
    internal use.

    Parameters
    ----------
    zs : 1-D ndarray
        Odd length symmetric z-series, ordered from  low to high.

    Returns
    -------
    c : 1-D ndarray
        Chebyshev coefficients, ordered from  low to high.

    """
    # Calculate the number of terms in the resulting Chebyshev series
    n = (zs.size + 1)//2
    # Copy the central part of zs to c, which becomes Chebyshev coefficients
    c = zs[n-1:].copy()
    # Double the coefficients from the second to the middle term
    c[1:n] *= 2
    return c


def _zseries_mul(z1, z2):
    """Multiply two z-series.

    Multiply two z-series to produce a z-series.

    Parameters
    ----------
    z1, z2 : 1-D ndarray
        The arrays must be 1-D but this is not checked.

    Returns
    -------
    product : 1-D ndarray
        The product z-series.

    Notes
    -----
    This is simply convolution. If symmetric/anti-symmetric z-series are
    denoted by S/A then the following rules apply:

    S*S, A*A -> S
    S*A, A*S -> A

    """
    # Compute the convolution of z1 and z2
    return np.convolve(z1, z2)


def _zseries_div(z1, z2):
    """Divide the first z-series by the second.

    Divide `z1` by `z2` and return the quotient and remainder as z-series.
    Warning: this implementation only applies when both z1 and z2 have the
    same symmetry, which is sufficient for present purposes.

    Parameters
    ----------
    z1, z2 : 1-D ndarray
        The arrays must be 1-D and have the same symmetry, but this is not
        checked.

    Returns
    -------

    (quotient, remainder) : 1-D ndarrays
        Quotient and remainder as z-series.

    Notes
    -----
    This is not the same as polynomial division on account of the desired form
    of the remainder. If symmetric/anti-symmetric z-series are denoted by S/A
    then the following rules apply:

    S/S -> S,S
    A/A -> S,A

    The restriction to types of the same symmetry could be fixed but seems like
    unneeded generality. There is no natural form for the remainder in the case
    where there is no symmetry.

    """
    # Make copies of z1 and z2
    z1 = z1.copy()
    z2 = z2.copy()
    # Get the lengths of z1 and z2
    lc1 = len(z1)
    lc2 = len(z2)
    # Case when z2 is a scalar
    if lc2 == 1:
        z1 /= z2
        return z1, z1[:1]*0
    # Case when z1 has fewer elements than z2
    elif lc1 < lc2:
        return z1[:1]*0, z1
    else:
        # Case when z1 has more elements than z2
        dlen = lc1 - lc2
        scl = z2[0]
        z2 /= scl
        quo = np.empty(dlen + 1, dtype=z1.dtype)
        i = 0
        j = dlen
        # Perform long division
        while i < j:
            r = z1[i]
            quo[i] = z1[i]
            quo[dlen - i] = r
            tmp = r*z2
            z1[i:i+lc2] -= tmp
            z1[j:j+lc2] -= tmp
            i += 1
            j -= 1
        r = z1[i]
        quo[i] = r
        tmp = r*z2
        z1[i:i+lc2] -= tmp
        quo /= scl
        rem = z1[i+1:i-1+lc2].copy()
        return quo, rem


def _zseries_der(zs):
    """Differentiate a z-series.

    The derivative is with respect to x, not z. This is achieved using the
    """
    # No code is provided for this function in the prompt
    pass
    # 计算输入 z-series 的导数,基于链式法则和模块注释中给出的 dx/dz 的值。

    Parameters
    ----------
    zs : z-series
        待求导的 z-series。

    Returns
    -------
    derivative : z-series
        导数结果。

    Notes
    -----
    对于 x 的 z-series (ns),已乘以二以避免使用与 Decimal 和其他特定标量类型不兼容的浮点数。
    为了补偿这种缩放效果,zs 的值也乘以二,这样两者在除法中相互抵消。

    """
    # 计算 ns 的长度并取整除以 2
    n = len(zs) // 2
    # 创建一个 numpy 数组 ns,包含 [-1, 0, 1],数据类型与 zs 相同
    ns = np.array([-1, 0, 1], dtype=zs.dtype)
    # 将 zs 的每个元素乘以对应位置的 (-n 到 n 的范围) * 2,以补偿之前的乘法操作
    zs *= np.arange(-n, n+1) * 2
    # 使用 _zseries_div 函数计算 zs 和 ns 的商,结果包括商 d 和余数 r
    d, r = _zseries_div(zs, ns)
    # 返回导数结果 d
    return d
# 将 z-series 进行积分处理,积分是相对于 x 而非 z。这是通过变量变换 dx/dz 来实现的,变换细节见模块注释。
def _zseries_int(zs):
    # 计算 z-series 的长度,并计算对应的 x-series 的长度
    n = 1 + len(zs)//2
    # 创建一个包含 [-1, 0, 1] 的 NumPy 数组,数据类型与 zs 相同
    ns = np.array([-1, 0, 1], dtype=zs.dtype)
    # 将 zs 乘以 x-series 的系数,以进行变量变换
    zs = _zseries_mul(zs, ns)
    # 创建一个数组,其值为 [-n*2, ..., -2, 0, 2, ..., n*2],用于后续的除法
    div = np.arange(-n, n+1)*2
    # 对 zs 进行分段除法,以完成变量变换后的调整
    zs[:n] /= div[:n]
    zs[n+1:] /= div[n+1:]
    # 将中间值置为 0,符合积分常数的定义
    zs[n] = 0
    # 返回处理后的 z-series,即 x-series 的积分结果
    return zs

#
# Chebyshev series functions
#


def poly2cheb(pol):
    """
    Convert a polynomial to a Chebyshev series.

    Convert an array representing the coefficients of a polynomial (relative
    to the "standard" basis) ordered from lowest degree to highest, to an
    array of the coefficients of the equivalent Chebyshev series, ordered
    from lowest to highest degree.

    Parameters
    ----------
    pol : array_like
        1-D array containing the polynomial coefficients

    Returns
    -------
    c : ndarray
        1-D array containing the coefficients of the equivalent Chebyshev
        series.

    See Also
    --------
    cheb2poly

    Notes
    -----
    The easy way to do conversions between polynomial basis sets
    is to use the convert method of a class instance.

    Examples
    --------
    >>> from numpy import polynomial as P
    >>> p = P.Polynomial(range(4))
    >>> p
    Polynomial([0., 1., 2., 3.], domain=[-1.,  1.], window=[-1.,  1.], symbol='x')
    >>> c = p.convert(kind=P.Chebyshev)
    >>> c
    Chebyshev([1.  , 3.25, 1.  , 0.75], domain=[-1.,  1.], window=[-1., ...
    >>> P.chebyshev.poly2cheb(range(4))
    array([1.  , 3.25, 1.  , 0.75])

    """
    # 使用 pu.as_series 将输入 pol 转换为 series
    [pol] = pu.as_series([pol])
    # 计算多项式的最高阶数
    deg = len(pol) - 1
    # 初始化结果为空的 Chebyshev 系数数组
    res = 0
    # 从最高阶开始逐步构建 Chebyshev 系数
    for i in range(deg, -1, -1):
        # 将当前多项式系数转换为 Chebyshev 系数并累加到 res 中
        res = chebadd(chebmulx(res), pol[i])
    # 返回转换后的 Chebyshev 系数数组
    return res


def cheb2poly(c):
    """
    Convert a Chebyshev series to a polynomial.

    Convert an array representing the coefficients of a Chebyshev series,
    ordered from lowest degree to highest, to an array of the coefficients
    of the equivalent polynomial (relative to the "standard" basis) ordered
    from lowest to highest degree.

    Parameters
    ----------
    c : array_like
        1-D array containing the Chebyshev series coefficients, ordered
        from lowest order term to highest.

    Returns
    -------
    pol : ndarray
        1-D array containing the coefficients of the equivalent polynomial
        (relative to the "standard" basis) ordered from lowest order term
        to highest.

    See Also
    --------
    poly2cheb

    Notes
    -----

    """
    # 该函数未实现详细注释,仅提供函数的基本结构和说明
    pass
    # 导入必要的函数和类来执行多项式操作
    from .polynomial import polyadd, polysub, polymulx
    
    # 将输入的多项式系数转换为系列(series),即确保 c 是一个多项式系数列表
    [c] = pu.as_series([c])
    
    # 计算多项式的阶数
    n = len(c)
    
    # 如果多项式阶数小于3,则直接返回多项式系数 c,不需要进行转换操作
    if n < 3:
        return c
    else:
        # 从 c 中提取倒数第二个系数和最后一个系数作为初始值
        c0 = c[-2]
        c1 = c[-1]
        
        # 从高阶到低阶(从 n-1 到 2),依次进行转换操作
        for i in range(n - 1, 1, -1):
            tmp = c0
            # 计算当前阶数 c1 的多项式转换结果
            c0 = polysub(c[i - 2], c1)
            c1 = polyadd(tmp, polymulx(c1)*2)
        
        # 返回转换后的多项式系数列表
        return polyadd(c0, polymulx(c1))
# 这些是整数类型的常量数组,以便与广泛的其他类型兼容,比如 Decimal。

# Chebyshev 默认定义域。
chebdomain = np.array([-1., 1.])

# 表示零的 Chebyshev 系数。
chebzero = np.array([0])

# 表示一的 Chebyshev 系数。
chebone = np.array([1])

# 表示恒等函数 x 的 Chebyshev 系数。
chebx = np.array([0, 1])


def chebline(off, scl):
    """
    表示一条直线的 Chebyshev 级数。

    Parameters
    ----------
    off, scl : scalar
        指定的直线由 ``off + scl*x`` 给出。

    Returns
    -------
    y : ndarray
        该模块对于 ``off + scl*x`` 的 Chebyshev 级数表示。

    See Also
    --------
    numpy.polynomial.polynomial.polyline
    numpy.polynomial.legendre.legline
    numpy.polynomial.laguerre.lagline
    numpy.polynomial.hermite.hermline
    numpy.polynomial.hermite_e.hermeline

    Examples
    --------
    >>> import numpy.polynomial.chebyshev as C
    >>> C.chebline(3,2)
    array([3, 2])
    >>> C.chebval(-3, C.chebline(3,2)) # 应该得到 -3
    -3.0

    """
    if scl != 0:
        return np.array([off, scl])
    else:
        return np.array([off])


def chebfromroots(roots):
    """
    生成具有给定根的 Chebyshev 级数。

    函数返回多项式

    .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n)

    的 Chebyshev 形式的系数,其中 :math:`r_n` 是 `roots` 中指定的根。如果一个零有多重性 n,
    那么它必须在 `roots` 中出现 n 次。例如,如果 2 是多重性为三的根,3 是多重性为两的根,
    那么 `roots` 看起来像是 [2, 2, 2, 3, 3]。根可以以任何顺序出现。

    如果返回的系数是 `c`,则

    .. math:: p(x) = c_0 + c_1 * T_1(x) + ... +  c_n * T_n(x)

    最后一项的系数通常不是 Chebyshev 形式的单项多项式的 1。

    Parameters
    ----------
    roots : array_like
        包含根的序列。

    Returns
    -------
    out : ndarray
        系数的一维数组。如果所有根都是实数,则 `out` 是实数组;如果某些根是复数,则 `out` 是复数,
        即使结果中的所有系数都是实数(见下面的示例)。

    See Also
    --------
    numpy.polynomial.polynomial.polyfromroots
    numpy.polynomial.legendre.legfromroots
    numpy.polynomial.laguerre.lagfromroots
    numpy.polynomial.hermite.hermfromroots
    numpy.polynomial.hermite_e.hermefromroots

    Examples
    --------
    >>> import numpy.polynomial.chebyshev as C
    >>> C.chebfromroots((-1,0,1)) # 相对于标准基础的 x^3 - x
    array([ 0.  , -0.25,  0.  ,  0.25])
    >>> j = complex(0,1)
    >>> C.chebfromroots((-j,j)) # 相对于标准基础的 x^2 + 1
    array([1.5+0.j, 0. +0.j, 0.5+0.j])

    """
    # 调用 pu 模块的 _fromroots 函数,传入 chebline、chebmul、roots 作为参数,并返回其结果
    return pu._fromroots(chebline, chebmul, roots)
# 定义函数 chebadd,用于将两个切比雪夫级数相加
def chebadd(c1, c2):
    # 调用私有函数 _add,执行切比雪夫级数的加法操作
    return pu._add(c1, c2)


# 定义函数 chebsub,用于从一个切比雪夫级数中减去另一个切比雪夫级数
def chebsub(c1, c2):
    # 调用私有函数 _sub,执行切比雪夫级数的减法操作
    return pu._sub(c1, c2)


# 定义函数 chebmulx,用于将一个切比雪夫级数乘以自变量 x
def chebmulx(c):
    """
    Multiply a Chebyshev series by x.

    Multiply the polynomial `c` by x, where x is the independent
    variable.

    Parameters
    ----------
    c : array_like
        1-D array of Chebyshev series coefficients ordered from low to
        high.

    Returns
    -------
    out : ndarray
        Array representing the result of the multiplication.

    See Also
    --------
    chebadd, chebsub, chebmul, chebdiv, chebpow

    Notes
    -----

    .. versionadded:: 1.5.0

    Examples
    --------
    >>> from numpy.polynomial import chebyshev as C
    >>> C.chebmulx([1,2,3])
    array([1. , 2.5, 1. , 1.5])

    """
    # 调用 pu.as_series([c]) 方法返回的结果,取其第一个元素作为 c
    [c] = pu.as_series([c])
    # 如果输入列表 c 的长度为1且唯一元素为0,则直接返回该列表,不进行后续计算
    if len(c) == 1 and c[0] == 0:
        return c

    # 创建一个长度为 len(c)+1 的空数组 prd,其数据类型与 c 相同
    prd = np.empty(len(c) + 1, dtype=c.dtype)
    
    # 将 prd 数组的第一个元素设置为 c[0] 的零乘积
    prd[0] = c[0]*0
    
    # 将 prd 数组的第二个元素设置为 c[0]
    prd[1] = c[0]
    
    # 如果 c 的长度大于1,则进行以下操作
    if len(c) > 1:
        # 将 c 的第二个元素及其后的元素都除以2,存储到 tmp 变量中
        tmp = c[1:]/2
        # 将 tmp 中的值赋给 prd 数组的第三个元素及其后的元素
        prd[2:] = tmp
        # 将 tmp 中的值累加到 prd 数组的倒数第二个元素及其前的元素上
        prd[0:-2] += tmp
    
    # 返回计算结果数组 prd
    return prd
# Multiply one Chebyshev series by another.
# 返回两个切比雪夫级数的乘积。
def chebmul(c1, c2):
    """
    Multiply one Chebyshev series by another.

    Returns the product of two Chebyshev series `c1` * `c2`.  The arguments
    are sequences of coefficients, from lowest order "term" to highest,
    e.g., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.

    Parameters
    ----------
    c1, c2 : array_like
        1-D arrays of Chebyshev series coefficients ordered from low to
        high.

    Returns
    -------
    out : ndarray
        Of Chebyshev series coefficients representing their product.

    See Also
    --------
    chebadd, chebsub, chebmulx, chebdiv, chebpow

    Notes
    -----
    In general, the (polynomial) product of two C-series results in terms
    that are not in the Chebyshev polynomial basis set.  Thus, to express
    the product as a C-series, it is typically necessary to "reproject"
    the product onto said basis set, which typically produces
    "unintuitive live" (but correct) results; see Examples section below.

    Examples
    --------
    >>> from numpy.polynomial import chebyshev as C
    >>> c1 = (1,2,3)
    >>> c2 = (3,2,1)
    >>> C.chebmul(c1,c2) # multiplication requires "reprojection"
    array([  6.5,  12. ,  12. ,   4. ,   1.5])

    """
    # Trim c1, c2 to ensure they are valid series
    [c1, c2] = pu.as_series([c1, c2])
    # Convert c1 to a z-series (series of complex numbers)
    z1 = _cseries_to_zseries(c1)
    # Convert c2 to a z-series
    z2 = _cseries_to_zseries(c2)
    # Multiply the z-series z1 and z2
    prd = _zseries_mul(z1, z2)
    # Convert the resulting z-series back to a Chebyshev series
    ret = _zseries_to_cseries(prd)
    # Trim any unnecessary zeros from the resulting series and return
    return pu.trimseq(ret)


# Divide one Chebyshev series by another.
# 返回两个切比雪夫级数的商和余数。
def chebdiv(c1, c2):
    """
    Divide one Chebyshev series by another.

    Returns the quotient-with-remainder of two Chebyshev series
    `c1` / `c2`.  The arguments are sequences of coefficients from lowest
    order "term" to highest, e.g., [1,2,3] represents the series
    ``T_0 + 2*T_1 + 3*T_2``.

    Parameters
    ----------
    c1, c2 : array_like
        1-D arrays of Chebyshev series coefficients ordered from low to
        high.

    Returns
    -------
    [quo, rem] : ndarrays
        Of Chebyshev series coefficients representing the quotient and
        remainder.

    See Also
    --------
    chebadd, chebsub, chebmulx, chebmul, chebpow

    Notes
    -----
    In general, the (polynomial) division of one C-series by another
    results in quotient and remainder terms that are not in the Chebyshev
    polynomial basis set.  Thus, to express these results as C-series, it
    is typically necessary to "reproject" the results onto said basis
    set, which typically produces "unintuitive" (but correct) results;
    see Examples section below.

    Examples
    --------
    >>> from numpy.polynomial import chebyshev as C
    >>> c1 = (1,2,3)
    >>> c2 = (3,2,1)
    >>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
    (array([3.]), array([-8., -4.]))
    >>> c2 = (0,1,2,3)
    >>> C.chebdiv(c2,c1) # neither "intuitive"
    (array([0., 2.]), array([-2., -4.]))

    """
    # Trim c1, c2 to ensure they are valid series
    [c1, c2] = pu.as_series([c1, c2])
    # 如果 c2 的最后一个元素为 0,则抛出 ZeroDivisionError 异常
    if c2[-1] == 0:
        raise ZeroDivisionError()

    # 注意:这种写法比 `pu._div(chebmul, c1, c2)` 更有效率

    # 计算 c1 和 c2 的长度
    lc1 = len(c1)
    lc2 = len(c2)

    # 根据 c1 和 c2 的长度关系进行不同的处理
    if lc1 < lc2:
        # 如果 c1 的长度小于 c2,则返回 (c1[0]*0, c1)
        return c1[:1]*0, c1
    elif lc2 == 1:
        # 如果 c2 的长度为 1,则返回 (c1/c2[-1], c1[0]*0)
        return c1/c2[-1], c1[:1]*0
    else:
        # 将 c1 和 c2 转换为复数系数表示
        z1 = _cseries_to_zseries(c1)
        z2 = _cseries_to_zseries(c2)
        
        # 对复数系数进行除法运算,得到商和余数
        quo, rem = _zseries_div(z1, z2)
        
        # 将得到的复数系数表示的商和余数转换为普通系数表示,并去除多余的零系数
        quo = pu.trimseq(_zseries_to_cseries(quo))
        rem = pu.trimseq(_zseries_to_cseries(rem))
        
        # 返回计算结果:商和余数
        return quo, rem
def chebpow(c, pow, maxpower=16):
    """Raise a Chebyshev series to a power.

    Returns the Chebyshev series `c` raised to the power `pow`. The
    argument `c` is a sequence of coefficients ordered from low to high.
    i.e., [1,2,3] is the series  ``T_0 + 2*T_1 + 3*T_2.``

    Parameters
    ----------
    c : array_like
        1-D array of Chebyshev series coefficients ordered from low to
        high.
    pow : integer
        Power to which the series will be raised
    maxpower : integer, optional
        Maximum power allowed. This is mainly to limit growth of the series
        to unmanageable size. Default is 16

    Returns
    -------
    coef : ndarray
        Chebyshev series of power.

    See Also
    --------
    chebadd, chebsub, chebmulx, chebmul, chebdiv

    Examples
    --------
    >>> from numpy.polynomial import chebyshev as C
    >>> C.chebpow([1, 2, 3, 4], 2)
    array([15.5, 22. , 16. , ..., 12.5, 12. ,  8. ])

    """
    # note: this is more efficient than `pu._pow(chebmul, c1, c2)`, as it
    # avoids converting between z and c series repeatedly

    # c is a trimmed copy
    [c] = pu.as_series([c])  # Convert `c` to a series if it's not already
    power = int(pow)  # Ensure `pow` is an integer
    if power != pow or power < 0:  # Check if `pow` is a non-negative integer
        raise ValueError("Power must be a non-negative integer.")
    elif maxpower is not None and power > maxpower:  # Check if `pow` exceeds `maxpower`
        raise ValueError("Power is too large")
    elif power == 0:  # Return 1 if power is 0
        return np.array([1], dtype=c.dtype)
    elif power == 1:  # Return `c` itself if power is 1
        return c
    else:
        # This can be made more efficient by using powers of two
        # in the usual way.
        zs = _cseries_to_zseries(c)  # Convert Chebyshev series `c` to z-series
        prd = zs
        for i in range(2, power + 1):
            prd = np.convolve(prd, zs)  # Perform convolution to compute higher powers
        return _zseries_to_cseries(prd)  # Convert back to Chebyshev series and return


def chebder(c, m=1, scl=1, axis=0):
    """
    Differentiate a Chebyshev series.

    Returns the Chebyshev series coefficients `c` differentiated `m` times
    along `axis`.  At each iteration the result is multiplied by `scl` (the
    scaling factor is for use in a linear change of variable). The argument
    `c` is an array of coefficients from low to high degree along each
    axis, e.g., [1,2,3] represents the series ``1*T_0 + 2*T_1 + 3*T_2``
    while [[1,2],[1,2]] represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) +
    2*T_0(x)*T_1(y) + 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is
    ``y``.

    Parameters
    ----------
    c : array_like
        Array of Chebyshev series coefficients. If c is multidimensional
        the different axis correspond to different variables with the
        degree in each axis given by the corresponding index.
    m : int, optional
        Number of derivatives taken, must be non-negative. (Default: 1)
    scl : scalar, optional
        Each differentiation is multiplied by `scl`.  The end result is
        multiplication by ``scl**m``.  This is for use in a linear change of
        variable. (Default: 1)
    axis : int, optional
        Axis along which differentiation is performed. (Default: 0)

    """
    # 将输入参数 `c` 转换为至少一维的 numpy 数组,并进行复制
    c = np.array(c, ndmin=1, copy=True)
    
    # 如果数组 `c` 的数据类型是布尔型、字节型、短整型、整型或长整型,则转换为双精度浮点型
    if c.dtype.char in '?bBhHiIlLqQpP':
        c = c.astype(np.double)
    
    # 将参数 `m` 转换为整数,表示导数的阶数
    cnt = pu._as_int(m, "the order of derivation")
    
    # 将参数 `axis` 转换为整数,表示进行导数计算的轴
    iaxis = pu._as_int(axis, "the axis")
    
    # 如果导数的阶数 `cnt` 小于 0,则抛出 ValueError 异常
    if cnt < 0:
        raise ValueError("The order of derivation must be non-negative")
    
    # 根据参数 `axis` 规范化轴的索引,确保在数组 `c` 的维度范围内
    iaxis = normalize_axis_index(iaxis, c.ndim)
    
    # 如果导数的阶数 `cnt` 等于 0,则直接返回输入数组 `c`
    if cnt == 0:
        return c
    
    # 将数组 `c` 的轴 `iaxis` 移动到最前面,便于后续计算
    c = np.moveaxis(c, iaxis, 0)
    
    # 获取数组 `c` 的长度 `n`
    n = len(c)
    
    # 如果导数的阶数 `cnt` 大于等于 `n`,则将数组 `c` 的前部分清零
    if cnt >= n:
        c = c[:1] * 0
    else:
        # 否则,进行导数的计算
        for i in range(cnt):
            n = n - 1
            c *= scl  # 将数组 `c` 各元素乘以缩放因子 `scl`
            # 创建空的导数数组 `der`,其形状与数组 `c` 的后续维度一致
            der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
            for j in range(n, 2, -1):
                # 计算 Chebyshev 多项式的导数
                der[j - 1] = (2 * j) * c[j]
                c[j - 2] += (j * c[j]) / (j - 2)
            if n > 1:
                der[1] = 4 * c[2]
            der[0] = c[1]
            c = der
    
    # 将导数计算后的数组 `c` 恢复原来的轴顺序,与输入数组 `c` 一致
    c = np.moveaxis(c, 0, iaxis)
    
    # 返回计算得到的 Chebyshev 多项式的导数数组 `c`
    return c
# 定义函数 chebint,用于对 Chebyshev 级数进行积分
def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
    """
    Integrate a Chebyshev series.

    Returns the Chebyshev series coefficients `c` integrated `m` times from
    `lbnd` along `axis`. At each iteration the resulting series is
    **multiplied** by `scl` and an integration constant, `k`, is added.
    The scaling factor is for use in a linear change of variable.  ("Buyer
    beware": note that, depending on what one is doing, one may want `scl`
    to be the reciprocal of what one might expect; for more information,
    see the Notes section below.)  The argument `c` is an array of
    coefficients from low to high degree along each axis, e.g., [1,2,3]
    represents the series ``T_0 + 2*T_1 + 3*T_2`` while [[1,2],[1,2]]
    represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) + 2*T_0(x)*T_1(y) +
    2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.

    Parameters
    ----------
    c : array_like
        Array of Chebyshev series coefficients. If c is multidimensional
        the different axis correspond to different variables with the
        degree in each axis given by the corresponding index.
    m : int, optional
        Order of integration, must be positive. (Default: 1)
    k : {[], list, scalar}, optional
        Integration constant(s).  The value of the first integral at zero
        is the first value in the list, the value of the second integral
        at zero is the second value, etc.  If ``k == []`` (the default),
        all constants are set to zero.  If ``m == 1``, a single scalar can
        be given instead of a list.
    lbnd : scalar, optional
        The lower bound of the integral. (Default: 0)
    scl : scalar, optional
        Following each integration the result is *multiplied* by `scl`
        before the integration constant is added. (Default: 1)
    axis : int, optional
        Axis over which the integral is taken. (Default: 0).

        .. versionadded:: 1.7.0

    Returns
    -------
    S : ndarray
        C-series coefficients of the integral.

    Raises
    ------
    ValueError
        If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
        ``np.ndim(scl) != 0``.

    See Also
    --------
    chebder

    Notes
    -----
    Note that the result of each integration is *multiplied* by `scl`.
    Why is this important to note?  Say one is making a linear change of
    variable :math:`u = ax + b` in an integral relative to `x`.  Then
    :math:`dx = du/a`, so one will need to set `scl` equal to
    :math:`1/a`- perhaps not what one would have first thought.

    Also note that, in general, the result of integrating a C-series needs
    to be "reprojected" onto the C-series basis set.  Thus, typically,
    the result of this function is "unintuitive," albeit correct; see
    Examples section below.

    Examples
    --------
    >>> from numpy.polynomial import chebyshev as C
    >>> c = (1,2,3)
    >>> C.chebint(c)
    array([ 0.5, -0.5,  0.5,  0.5])
    >>> C.chebint(c,3)

    """
    # 将输入的参数 c 转换为至少有一维的 numpy 数组,并保留其副本
    c = np.array(c, ndmin=1, copy=True)
    
    # 如果数组 c 的数据类型为布尔型或整型,将其转换为双精度浮点型
    if c.dtype.char in '?bBhHiIlLqQpP':
        c = c.astype(np.double)
    
    # 如果参数 k 不可迭代(即非列表或数组),将其转换为列表
    if not np.iterable(k):
        k = [k]
    
    # 将参数 m 规范化为整数,表示积分的阶数
    cnt = pu._as_int(m, "the order of integration")
    
    # 将参数 axis 规范化为整数,表示操作的轴
    iaxis = pu._as_int(axis, "the axis")
    
    # 如果积分的阶数 cnt 小于 0,抛出 ValueError 异常
    if cnt < 0:
        raise ValueError("The order of integration must be non-negative")
    
    # 如果 k 的长度大于 cnt,抛出 ValueError 异常
    if len(k) > cnt:
        raise ValueError("Too many integration constants")
    
    # 如果 lbnd 不是标量,抛出 ValueError 异常
    if np.ndim(lbnd) != 0:
        raise ValueError("lbnd must be a scalar.")
    
    # 如果 scl 不是标量,抛出 ValueError 异常
    if np.ndim(scl) != 0:
        raise ValueError("scl must be a scalar.")
    
    # 将操作的轴 iaxis 规范化,确保其在 c 的维度范围内
    iaxis = normalize_axis_index(iaxis, c.ndim)
    
    # 如果积分的阶数 cnt 等于 0,直接返回参数 c,无需积分计算
    if cnt == 0:
        return c
    
    # 将 c 数组中的轴移动到索引位置 0,方便后续的积分操作
    c = np.moveaxis(c, iaxis, 0)
    
    # 将列表 k 补充到长度为 cnt,不足部分用 0 填充
    k = list(k) + [0]*(cnt - len(k))
    
    # 开始进行积分操作,循环 cnt 次
    for i in range(cnt):
        n = len(c)  # 获取当前 c 数组的长度
        c *= scl  # 将 c 数组中的所有元素乘以标量 scl
    
        # 如果 c 数组长度为 1,且其唯一元素为 0,则在该元素上加上 k[i]
        if n == 1 and np.all(c[0] == 0):
            c[0] += k[i]
        else:
            # 创建一个临时数组 tmp,用于存储积分过程中的中间结果
            tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
            tmp[0] = c[0]*0  # 第一个元素为 0
            tmp[1] = c[0]  # 第二个元素为 c[0]
    
            # 如果 n 大于 1,则计算后续元素的值
            if n > 1:
                tmp[2] = c[1]/4
            for j in range(2, n):
                tmp[j + 1] = c[j]/(2*(j + 1))
                tmp[j - 1] -= c[j]/(2*(j - 1))
    
            # 计算 tmp[0],加上 k[i] 减去 chebval(lbnd, tmp) 的值
            tmp[0] += k[i] - chebval(lbnd, tmp)
            c = tmp
    
    # 完成积分操作后,将 c 数组中的轴移回到原始位置 iaxis
    c = np.moveaxis(c, 0, iaxis)
    
    # 返回最终的积分结果数组 c
    return c
def chebval(x, c, tensor=True):
    """
    Evaluate a Chebyshev series at points x.

    If `c` is of length `n + 1`, this function returns the value:

    .. math:: p(x) = c_0 * T_0(x) + c_1 * T_1(x) + ... + c_n * T_n(x)

    The parameter `x` is converted to an array only if it is a tuple or a
    list, otherwise it is treated as a scalar. In either case, either `x`
    or its elements must support multiplication and addition both with
    themselves and with the elements of `c`.

    If `c` is a 1-D array, then ``p(x)`` will have the same shape as `x`.  If
    `c` is multidimensional, then the shape of the result depends on the
    value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
    x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
    scalars have shape (,).

    Trailing zeros in the coefficients will be used in the evaluation, so
    they should be avoided if efficiency is a concern.

    Parameters
    ----------
    x : array_like, compatible object
        If `x` is a list or tuple, it is converted to an ndarray, otherwise
        it is left unchanged and treated as a scalar. In either case, `x`
        or its elements must support addition and multiplication with
        themselves and with the elements of `c`.
    c : array_like
        Array of coefficients ordered so that the coefficients for terms of
        degree n are contained in c[n]. If `c` is multidimensional the
        remaining indices enumerate multiple polynomials. In the two
        dimensional case the coefficients may be thought of as stored in
        the columns of `c`.
    tensor : boolean, optional
        If True, the shape of the coefficient array is extended with ones
        on the right, one for each dimension of `x`. Scalars have dimension 0
        for this action. The result is that every column of coefficients in
        `c` is evaluated for every element of `x`. If False, `x` is broadcast
        over the columns of `c` for the evaluation.  This keyword is useful
        when `c` is multidimensional. The default value is True.

        .. versionadded:: 1.7.0

    Returns
    -------
    values : ndarray, algebra_like
        The shape of the return value is described above.

    See Also
    --------
    chebval2d, chebgrid2d, chebval3d, chebgrid3d

    Notes
    -----
    The evaluation uses Clenshaw recursion, aka synthetic division.

    """
    # 将输入的系数数组转换成至少为1维的 numpy 数组,确保数据可用性和一致性
    c = np.array(c, ndmin=1, copy=True)
    # 如果系数数组的数据类型是布尔型或整型,则转换为双精度浮点型
    if c.dtype.char in '?bBhHiIlLqQpP':
        c = c.astype(np.double)
    # 如果输入的 x 是列表或元组,则转换为 ndarray 数组
    if isinstance(x, (tuple, list)):
        x = np.asarray(x)
    # 如果 x 是 ndarray 类型且 tensor 为 True,则调整系数数组的形状以便广播计算
    if isinstance(x, np.ndarray) and tensor:
        c = c.reshape(c.shape + (1,)*x.ndim)

    # 根据系数数组的长度选择不同的计算方法
    if len(c) == 1:
        c0 = c[0]
        c1 = 0
    elif len(c) == 2:
        c0 = c[0]
        c1 = c[1]
    else:
        x2 = 2*x
        c0 = c[-2]
        c1 = c[-1]
        # 使用 Clenshaw 递归方法计算 Chebyshev 多项式的值
        for i in range(3, len(c) + 1):
            tmp = c0
            c0 = c[-i] - c1
            c1 = tmp + c1*x2
    # 返回表达式 c0 + c1*x 的计算结果
    return c0 + c1*x
# 在给定点(x, y)评估二维切比雪夫级数。

def chebval2d(x, y, c):
    # 调用 pu 模块的 _valnd 函数,用于评估二维切比雪夫级数的值。
    return pu._valnd(chebval, c, x, y)


# 在 x 和 y 的笛卡尔积上评估二维切比雪夫级数。

def chebgrid2d(x, y, c):
    # 返回值为在网格点 (a, b) 上的二维切比雪夫级数值。

    # 如果 c 的维度少于两个,隐式添加维度使其成为二维数组。
    # 结果的形状将为 c.shape[2:] + x.shape + y.shape。
    c : array_like
        # 输入参数 c 是一个类数组结构,包含系数,按照多重度量 i,j 的系数存储在 `c[i,j]` 中。
        # 如果 `c` 的维度高于两个,其余的索引用来枚举多组系数。

    Returns
    -------
    values : ndarray, compatible object
        # 返回值 `values` 是一个 ndarray 或兼容对象,包含二维切比雪夫级数在笛卡尔积 `x` 和 `y` 点上的值。

    See Also
    --------
    chebval, chebval2d, chebval3d, chebgrid3d
        # 参见其他相关函数:chebval, chebval2d, chebval3d, chebgrid3d。

    Notes
    -----
    .. versionadded:: 1.7.0
        # 添加于版本 1.7.0。

    """
    # 调用内部函数 `_gridnd`,计算二维切比雪夫系列在给定参数下的值
    return pu._gridnd(chebval, c, x, y)
# 计算三维切比雪夫级数在点 (x, y, z) 处的值。
def chebval3d(x, y, z, c):
    # 调用 _valnd 函数来计算三维切比雪夫级数的值,传入的参数是 chebval, c, x, y, z。
    return pu._valnd(chebval, c, x, y, z)


# 在 x、y 和 z 的笛卡尔积上评估三维切比雪夫级数。
def chebgrid3d(x, y, z, c):
    # 返回值是在点 (a, b, c) 处的值,其中 a 取自 x,b 取自 y,c 取自 z,使用三维切比雪夫多项式系数 c。
    # 结果点形成一个网格,x 在第一维,y 在第二维,z 在第三维。
    # 参数 x, y 和 z 如果是元组或列表,则转换为数组;否则视为标量。
    # 如果 c 的维度少于三维,会隐式添加维度使其变为三维。
    # 返回值的形状将是 c.shape[3:] + x.shape + y.shape + z.shape。
    return pu._valnd(chebval, c, x, y, z)
    x, y, z : array_like, compatible objects
        三维系列在`x`、`y`和`z`的笛卡尔积中的点上进行评估。如果`x`、`y`或`z`是列表或元组,则首先转换为ndarray,否则保持不变,如果它不是ndarray,则视为标量。
    c : array_like
        有序系数数组,使得度为i、j的项的系数包含在`c[i,j]`中。如果`c`的维度大于两个,则其余的索引列举多组系数。

    Returns
    -------
    values : ndarray, compatible object
        在`x`和`y`的笛卡尔积中点上的二维多项式的值。

    See Also
    --------
    chebval, chebval2d, chebgrid2d, chebval3d

    Notes
    -----

    .. versionadded:: 1.7.0

    """
    使用`chebval`函数计算在给定参数下的多项式值,并通过`pu._gridnd`进行网格化处理。
def chebvander(x, deg):
    """Pseudo-Vandermonde matrix of given degree.

    Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
    `x`. The pseudo-Vandermonde matrix is defined by

    .. math:: V[..., i] = T_i(x),

    where ``0 <= i <= deg``. The leading indices of `V` index the elements of
    `x` and the last index is the degree of the Chebyshev polynomial.

    If `c` is a 1-D array of coefficients of length ``n + 1`` and `V` is the
    matrix ``V = chebvander(x, n)``, then ``np.dot(V, c)`` and
    ``chebval(x, c)`` are the same up to roundoff.  This equivalence is
    useful both for least squares fitting and for the evaluation of a large
    number of Chebyshev series of the same degree and sample points.

    Parameters
    ----------
    x : array_like
        Array of points. The dtype is converted to float64 or complex128
        depending on whether any of the elements are complex. If `x` is
        scalar it is converted to a 1-D array.
    deg : int
        Degree of the resulting matrix.

    Returns
    -------
    vander : ndarray
        The pseudo Vandermonde matrix. The shape of the returned matrix is
        ``x.shape + (deg + 1,)``, where The last index is the degree of the
        corresponding Chebyshev polynomial.  The dtype will be the same as
        the converted `x`.

    """
    # Convert deg to an integer if possible, raising a ValueError if deg < 0
    ideg = pu._as_int(deg, "deg")
    if ideg < 0:
        raise ValueError("deg must be non-negative")

    # Ensure x is converted to a 1-D array of type float64 or complex128
    x = np.array(x, copy=None, ndmin=1) + 0.0
    # Create dimensions for the result matrix v
    dims = (ideg + 1,) + x.shape
    dtyp = x.dtype
    # Create an uninitialized array v with specified dimensions and type
    v = np.empty(dims, dtype=dtyp)

    # Use forward recursion to generate the entries of v
    v[0] = x*0 + 1  # Initialize the first row of v
    if ideg > 0:
        x2 = 2*x
        v[1] = x  # Initialize the second row of v
        # Use recursion to fill in the remaining rows of v
        for i in range(2, ideg + 1):
            v[i] = v[i-1]*x2 - v[i-2]

    # Move the first axis to the last axis to match the expected output shape
    return np.moveaxis(v, 0, -1)


def chebvander2d(x, y, deg):
    """Pseudo-Vandermonde matrix of given degrees.

    Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
    points ``(x, y)``. The pseudo-Vandermonde matrix is defined by

    .. math:: V[..., (deg[1] + 1)*i + j] = T_i(x) * T_j(y),

    where ``0 <= i <= deg[0]`` and ``0 <= j <= deg[1]``. The leading indices of
    `V` index the points ``(x, y)`` and the last index encodes the degrees of
    the Chebyshev polynomials.

    If ``V = chebvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
    correspond to the elements of a 2-D coefficient array `c` of shape
    (xdeg + 1, ydeg + 1) in the order

    .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...

    and ``np.dot(V, c.flat)`` and ``chebval2d(x, y, c)`` will be the same
    up to roundoff. This equivalence is useful both for least squares
    fitting and for the evaluation of a large number of 2-D Chebyshev
    series of the same degrees and sample points.

    Parameters
    ----------
    x : array_like
        Array of points for the first dimension.
    y : array_like
        Array of points for the second dimension.
    deg : list or tuple
        List or tuple specifying the degrees of the resulting matrix along each dimension.

    Returns
    -------
    vander : ndarray
        The pseudo Vandermonde matrix. The shape of the returned matrix is
        ``x.shape + y.shape + (np.prod(deg) + 1,)``. The last index is the degree of the
        corresponding 2-D Chebyshev polynomial. The dtype will be the same as
        the dtype of the concatenated `x` and `y`.

    """
    x, y : array_like
        Arrays of point coordinates, all of the same shape. The dtypes
        will be converted to either float64 or complex128 depending on
        whether any of the elements are complex. Scalars are converted to
        1-D arrays.
    deg : list of ints
        List of maximum degrees of the form [x_deg, y_deg].

    Returns
    -------
    vander2d : ndarray
        The shape of the returned matrix is ``x.shape + (order,)``, where
        :math:`order = (deg[0]+1)*(deg[1]+1)`.  The dtype will be the same
        as the converted `x` and `y`.

    See Also
    --------
    chebvander, chebvander3d, chebval2d, chebval3d

    Notes
    -----

    .. versionadded:: 1.7.0

    """
    # 调用 _vander_nd_flat 函数计算 2D Vandermonde 矩阵
    return pu._vander_nd_flat((chebvander, chebvander), (x, y), deg)
# 导入 pu 模块,该模块包含了 _vander_nd_flat 函数
import pu

# 计算 3D Chebyshev 矩阵的伪范德蒙德矩阵
def chebvander3d(x, y, z, deg):
    """Pseudo-Vandermonde matrix of given degrees.

    Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
    points ``(x, y, z)``. If `l`, `m`, `n` are the given degrees in `x`, `y`, `z`,
    then The pseudo-Vandermonde matrix is defined by

    .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = T_i(x)*T_j(y)*T_k(z),

    where ``0 <= i <= l``, ``0 <= j <= m``, and ``0 <= j <= n``.  The leading
    indices of `V` index the points ``(x, y, z)`` and the last index encodes
    the degrees of the Chebyshev polynomials.

    If ``V = chebvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
    of `V` correspond to the elements of a 3-D coefficient array `c` of
    shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order

    .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...

    and ``np.dot(V, c.flat)`` and ``chebval3d(x, y, z, c)`` will be the
    same up to roundoff. This equivalence is useful both for least squares
    fitting and for the evaluation of a large number of 3-D Chebyshev
    series of the same degrees and sample points.

    Parameters
    ----------
    x, y, z : array_like
        Arrays of point coordinates, all of the same shape. The dtypes will
        be converted to either float64 or complex128 depending on whether
        any of the elements are complex. Scalars are converted to 1-D
        arrays.
    deg : list of ints
        List of maximum degrees of the form [x_deg, y_deg, z_deg].

    Returns
    -------
    vander3d : ndarray
        The shape of the returned matrix is ``x.shape + (order,)``, where
        :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`.  The dtype will
        be the same as the converted `x`, `y`, and `z`.

    See Also
    --------
    chebvander, chebvander3d, chebval2d, chebval3d

    Notes
    -----

    .. versionadded:: 1.7.0

    """
    # 调用 _vander_nd_flat 函数来计算伪范德蒙德矩阵
    return pu._vander_nd_flat((chebvander, chebvander, chebvander), (x, y, z), deg)


# Chebyshev 多项式最小二乘拟合
def chebfit(x, y, deg, rcond=None, full=False, w=None):
    """
    Least squares fit of Chebyshev series to data.

    Return the coefficients of a Chebyshev series of degree `deg` that is the
    least squares fit to the data values `y` given at points `x`. If `y` is
    1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
    fits are done, one for each column of `y`, and the resulting
    coefficients are stored in the corresponding columns of a 2-D return.
    The fitted polynomial(s) are in the form

    .. math::  p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x),

    where `n` is `deg`.

    Parameters
    ----------
    x : array_like, shape (M,)
        x-coordinates of the M sample points ``(x[i], y[i])``.
    y : array_like, shape (M,) or (M, K)
        y-coordinates of the sample points. Several data sets of sample
        points sharing the same x-coordinates can be fitted at once by
        passing in a 2D-array that contains one dataset per column.
    deg : int
        Degree of the Chebyshev series to be used for the fit.
    rcond : float, optional
        Cutoff for small singular values.
    full : bool, optional
        If True, return additional outputs.
    w : array_like, optional
        Weights applied to the y-coordinates.

    Returns
    -------
    coef : ndarray
        Coefficients of the Chebyshev series, with shape (deg + 1,) or
        (deg + 1, K) if `y` is 2-D.
    residuals, rank, s : ndarray, int, ndarray
        Optional outputs as determined by `full`.

    See Also
    --------
    chebvander, chebvander2d, chebvander3d, chebval, chebval2d, chebval3d

    Notes
    -----
    This function is generally preferred over polyfit when the fitting
    is done with respect to Chebyshev series due to its better numerical
    properties.

    """
    pass  # 这个函数仅作为占位符,没有实际代码实现
    deg : int or 1-D array_like
        # 多项式拟合的阶数或阶数组成的一维数组。如果 `deg` 是一个整数,
        # 则包括从0阶到`deg`阶的所有项。对于 NumPy 版本 >= 1.11.0,可以使用
        # 整数列表指定要包含的项的阶数。

    rcond : float, optional
        # 拟合中使用的相对条件数。比最大奇异值小于此值的奇异值将被忽略。
        # 默认值是 `len(x)*eps`,其中 eps 是浮点类型的相对精度,
        # 在大多数情况下约为2e-16。

    full : bool, optional
        # 决定返回值的性质的开关。当为 False(默认值)时,仅返回系数;
        # 当为 True 时,还返回奇异值分解的诊断信息。

    w : array_like, shape (`M`,), optional
        # 权重数组。如果不为 None,则权重 `w[i]` 应用于 `x[i]` 处的非平方残差 `y[i] - y_hat[i]`。
        # 理想情况下,权重应选择使得所有产品 `w[i]*y[i]` 的误差具有相同的方差。
        # 当使用逆方差加权时,使用 `w[i] = 1/sigma(y[i])`。
        # 默认值为 None。

        .. versionadded:: 1.5.0
            # 添加于 NumPy 1.5.0 版本。

    Returns
    -------
    coef : ndarray, shape (M,) or (M, K)
        # 从低到高排序的切比雪夫系数。如果 `y` 是二维的,则第 k 列数据的系数位于第 k 列中。

    [residuals, rank, singular_values, rcond] : list
        # 仅当 `full == True` 时返回这些值。

        - residuals -- 最小二乘拟合的残差平方和
        - rank -- 缩放后的范德蒙矩阵的数值秩
        - singular_values -- 缩放后的范德蒙矩阵的奇异值
        - rcond -- `rcond` 的值

        详细信息请参见 `numpy.linalg.lstsq`。

    Warns
    -----
    RankWarning
        # 在最小二乘拟合的系数矩阵的秩不足时发出警告。仅当 `full == False` 时才会引发警告。
        # 可以通过以下方式关闭警告:

        >>> import warnings
        >>> warnings.simplefilter('ignore', np.exceptions.RankWarning)

    See Also
    --------
    numpy.polynomial.polynomial.polyfit
    numpy.polynomial.legendre.legfit
    numpy.polynomial.laguerre.lagfit
    numpy.polynomial.hermite.hermfit
    numpy.polynomial.hermite_e.hermefit
    chebval : 计算切比雪夫级数的值。
    chebvander : 切比雪夫级数的范德蒙矩阵。
    chebweight : 切比雪夫权重函数。
    numpy.linalg.lstsq : 从矩阵计算最小二乘拟合。
    scipy.interpolate.UnivariateSpline : 计算样条拟合。

    Notes
    -----
    # 解决方案是切比雪夫级数 `p` 的系数,该级数最小化加权平方误差的和。

    .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
    # 返回使用 `_fit` 函数进行拟合后的结果
    return pu._fit(chebvander, x, y, deg, rcond, full, w)
    # c is a trimmed copy
    [c] = pu.as_series([c])
    # Ensure the input coefficient array `c` is treated as a 1-D series
    # using the `pu.as_series` function from the `pu` module.

    if len(c) < 2:
        # Raise an error if the series length is less than 2,
        # as a Chebyshev series must have at least degree 1.
        raise ValueError('Series must have maximum degree of at least 1.')

    if len(c) == 2:
        # Return a 1x1 array with the root of the linear polynomial if its length is 2.
        return np.array([[-c[0]/c[1]]])

    # Calculate the degree of the polynomial represented by `c`.
    n = len(c) - 1
    # Initialize a square matrix `mat` of zeros with dimensions (n, n),
    # using the data type of `c`.
    mat = np.zeros((n, n), dtype=c.dtype)
    
    # Create an array `scl` containing scaling factors for the companion matrix,
    # where the first element is 1 and subsequent elements are square root of 0.5.
    scl = np.array([1.] + [np.sqrt(.5)]*(n-1))
    
    # Extract the top and bottom diagonals of the reshaped matrix `mat`.
    top = mat.reshape(-1)[1::n+1]
    bot = mat.reshape(-1)[n::n+1]
    
    # Set specific values in `top` and `bot` arrays to improve eigenvalue estimates.
    top[0] = np.sqrt(.5)
    top[1:] = 1/2
    bot[...] = top
    
    # Adjust the last column of `mat` using coefficients from `c` to form the scaled
    # companion matrix, enhancing stability and eigenvalue accuracy.
    mat[:, -1] -= (c[:-1]/c[-1])*(scl/scl[-1])*.5

    # Return the scaled companion matrix `mat`.
    return mat
    # 计算矩阵 m 的特征值
    r = la.eigvals(m)
    # 对特征值列表进行排序(默认是按照实部的大小进行排序)
    r.sort()
    # 返回排序后的特征值列表
    return r
# 使用切比雪夫点的第一类插值法插值函数 `func`。
def chebinterpolate(func, deg, args=()):
    """Interpolate a function at the Chebyshev points of the first kind.

    Returns the Chebyshev series that interpolates `func` at the Chebyshev
    points of the first kind in the interval [-1, 1]. The interpolating
    series tends to a minmax approximation to `func` with increasing `deg`
    if the function is continuous in the interval.

    .. versionadded:: 1.14.0

    Parameters
    ----------
    func : function
        The function to be approximated. It must be a function of a single
        variable of the form ``f(x, a, b, c...)``, where ``a, b, c...`` are
        extra arguments passed in the `args` parameter.
    deg : int
        Degree of the interpolating polynomial
    args : tuple, optional
        Extra arguments to be used in the function call. Default is no extra
        arguments.

    Returns
    -------
    coef : ndarray, shape (deg + 1,)
        Chebyshev coefficients of the interpolating series ordered from low to
        high.

    Examples
    --------
    >>> import numpy.polynomial.chebyshev as C
    >>> C.chebinterpolate(lambda x: np.tanh(x) + 0.5, 8)
    array([  5.00000000e-01,   8.11675684e-01,  -9.86864911e-17,
            -5.42457905e-02,  -2.71387850e-16,   4.51658839e-03,
             2.46716228e-17,  -3.79694221e-04,  -3.26899002e-16])

    Notes
    -----

    The Chebyshev polynomials used in the interpolation are orthogonal when
    sampled at the Chebyshev points of the first kind. If it is desired to
    constrain some of the coefficients they can simply be set to the desired
    value after the interpolation, no new interpolation or fit is needed. This
    is especially useful if it is known apriori that some of coefficients are
    zero. For instance, if the function is even then the coefficients of the
    terms of odd degree in the result can be set to zero.

    """
    # 将 deg 转换为 NumPy 数组,确保其为一维整数类型
    deg = np.asarray(deg)

    # 检查参数
    if deg.ndim > 0 or deg.dtype.kind not in 'iu' or deg.size == 0:
        raise TypeError("deg must be an int")
    if deg < 0:
        raise ValueError("expected deg >= 0")

    # 计算插值多项式的阶数
    order = deg + 1

    # 获取切比雪夫点的第一类
    xcheb = chebpts1(order)

    # 计算函数在切比雪夫点的第一类上的取值
    yfunc = func(xcheb, *args)

    # 计算切比雪夫多项式的伴随矩阵
    m = chebvander(xcheb, deg)

    # 计算插值多项式的系数
    c = np.dot(m.T, yfunc)

    # 将首个系数除以阶数
    c[0] /= order

    # 将其余系数除以 0.5 倍的阶数
    c[1:] /= 0.5 * order

    return c


# Gauss-Chebyshev 积分
def chebgauss(deg):
    """
    Gauss-Chebyshev quadrature.

    Computes the sample points and weights for Gauss-Chebyshev quadrature.
    These sample points and weights will correctly integrate polynomials of
    degree :math:`2*deg - 1` or less over the interval :math:`[-1, 1]` with
    the weight function :math:`f(x) = 1/\\sqrt{1 - x^2}`.

    Parameters
    ----------
    deg : int
        Number of sample points and weights. It must be >= 1.

    Returns
    -------
    x : ndarray
        1-D ndarray containing the sample points.
    y : ndarray
        1-D ndarray containing the weights.

    Notes
    -----

    .. versionadded:: 1.7.0


    """
    """
        The results have only been tested up to degree 100, higher degrees may
        be problematic. For Gauss-Chebyshev there are closed form solutions for
        the sample points and weights. If n = `deg`, then
    
        .. math:: x_i = \\cos(\\pi (2 i - 1) / (2 n))
    
        .. math:: w_i = \\pi / n
    
        """
    
        # 将 deg 转换为整数
        ideg = pu._as_int(deg, "deg")
    
        # 如果 ideg 小于等于 0,则抛出数值错误
        if ideg <= 0:
            raise ValueError("deg must be a positive integer")
    
        # 根据 Gauss-Chebyshev 公式计算采样点 x_i
        x = np.cos(np.pi * np.arange(1, 2*ideg, 2) / (2.0*ideg))
        
        # 设置权重 w_i,每个权重为 π/n
        w = np.ones(ideg)*(np.pi/ideg)
    
        # 返回计算得到的采样点 x 和权重 w
        return x, w
# 定义了一个计算第一类切比雪夫点的函数
def chebpts1(npts):
    # 将 npts 转换为整数
    _npts = int(npts)
    # 检查 npts 是否与 _npts 不相等,如果不相等则抛出值错误异常
    if _npts != npts:
        raise ValueError("npts must be integer")
    # 检查 _npts 是否小于 1,如果是则抛出值错误异常
    if _npts < 1:
        raise ValueError("npts must be >= 1")

    # 计算切比雪夫点的角度值,x = [pi*(k + .5)/npts for k in range(npts)]
    x = 0.5 * np.pi / _npts * np.arange(-_npts+1, _npts+1, 2)
    # 返回计算得到的切比雪夫点的第一类函数值的正弦值
    return np.sin(x)


# 定义了一个计算第二类切比雪夫点的函数
def chebpts2(npts):
    # 将 npts 转换为整数
    _npts = int(npts)
    # 检查 npts 是否与 _npts 不相等,如果不相等则抛出值错误异常
    if _npts != npts:
        raise ValueError("npts must be integer")
    # 检查 _npts 是否小于 2,如果是则抛出值错误异常
    if _npts < 2:
        raise ValueError("npts must be >= 2")

    # 计算切比雪夫点的角度值,x = [pi*k/(npts - 1) for k in range(npts)],并按升序排序
    x = np.linspace(-np.pi, 0, _npts)
    # 返回计算得到的切比雪夫点的第二类函数值的余弦值
    return np.cos(x)


# Chebyshev 类,继承自 ABCPolyBase 类
class Chebyshev(ABCPolyBase):
    """A Chebyshev series class.

    The Chebyshev class provides the standard Python numerical methods
    '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
    attributes and methods listed below.

    Parameters
    ----------
    coef : array_like
        Chebyshev coefficients in order of increasing degree, i.e.,
        ``(1, 2, 3)`` gives ``1*T_0(x) + 2*T_1(x) + 3*T_2(x)``.
    domain : (2,) array_like, optional
        Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
        to the interval ``[window[0], window[1]]`` by shifting and scaling.
        The default value is [-1, 1].
    window : (2,) array_like, optional
        Window, see `domain` for its use. The default value is [-1, 1].

        .. versionadded:: 1.6.0

    """
    pass
    symbol : str, optional
        Symbol used to represent the independent variable in string
        representations of the polynomial expression, e.g. for printing.
        The symbol must be a valid Python identifier. Default value is 'x'.

        .. versionadded:: 1.24

    """
    # 定义一些虚拟函数,这些函数用于处理 Chebyshev 多项式的各种运算
    _add = staticmethod(chebadd)
    _sub = staticmethod(chebsub)
    _mul = staticmethod(chebmul)
    _div = staticmethod(chebdiv)
    _pow = staticmethod(chebpow)
    _val = staticmethod(chebval)
    _int = staticmethod(chebint)
    _der = staticmethod(chebder)
    _fit = staticmethod(chebfit)
    _line = staticmethod(chebline)
    _roots = staticmethod(chebroots)
    _fromroots = staticmethod(chebfromroots)

    @classmethod
    def interpolate(cls, func, deg, domain=None, args=()):
        """Interpolate a function at the Chebyshev points of the first kind.

        Returns the series that interpolates `func` at the Chebyshev points of
        the first kind scaled and shifted to the `domain`. The resulting series
        tends to a minmax approximation of `func` when the function is
        continuous in the domain.

        .. versionadded:: 1.14.0

        Parameters
        ----------
        func : function
            The function to be interpolated. It must be a function of a single
            variable of the form ``f(x, a, b, c...)``, where ``a, b, c...`` are
            extra arguments passed in the `args` parameter.
        deg : int
            Degree of the interpolating polynomial.
        domain : {None, [beg, end]}, optional
            Domain over which `func` is interpolated. The default is None, in
            which case the domain is [-1, 1].
        args : tuple, optional
            Extra arguments to be used in the function call. Default is no
            extra arguments.

        Returns
        -------
        polynomial : Chebyshev instance
            Interpolating Chebyshev instance.

        Notes
        -----
        See `numpy.polynomial.chebinterpolate` for more details.

        """
        if domain is None:
            domain = cls.domain
        # 创建一个函数 xfunc,将 func 在指定 domain 上的映射和参数 args 一起应用
        xfunc = lambda x: func(pu.mapdomain(x, cls.window, domain), *args)
        # 调用 chebinterpolate 函数生成系数 coef
        coef = chebinterpolate(xfunc, deg)
        # 返回一个 Chebyshev 实例,以 coef 作为系数,domain 作为定义域
        return cls(coef, domain=domain)

    # 定义一些虚拟属性
    domain = np.array(chebdomain)
    window = np.array(chebdomain)
    basis_name = 'T'