NumPy-源码解析-三十-

16 阅读1小时+

NumPy 源码解析(三十)

.\numpy\numpy\ma\tests\test_deprecations.py

# 导入 pytest 库,用于测试和断言
import pytest
# 导入 numpy 库,并用 np 别名表示
import numpy as np
# 从 numpy.testing 模块导入 assert_warns 函数,用于检查是否产生特定警告
from numpy.testing import assert_warns
# 从 numpy.ma.testutils 模块导入 assert_equal 函数,用于比较两个对象是否相等
from numpy.ma.testutils import assert_equal
# 从 numpy.ma.core 模块导入 MaskedArrayFutureWarning 警告
from numpy.ma.core import MaskedArrayFutureWarning
# 导入 io 模块,用于操作输入输出流
import io
# 导入 textwrap 模块,用于处理文本缩进
import textwrap

# 定义一个名为 TestArgsort 的测试类
class TestArgsort:
    """ gh-8701 """

    # 定义一个辅助测试方法,接受 argsort 和 cls 作为参数
    def _test_base(self, argsort, cls):
        # 创建一个零维数组,并将其视图设置为 cls 类型
        arr_0d = np.array(1).view(cls)
        # 对零维数组进行 argsort 操作
        argsort(arr_0d)

        # 创建一个一维数组,并将其视图设置为 cls 类型
        arr_1d = np.array([1, 2, 3]).view(cls)
        # 对一维数组进行 argsort 操作
        argsort(arr_1d)

        # 创建一个二维数组,并将其视图设置为 cls 类型
        arr_2d = np.array([[1, 2], [3, 4]]).view(cls)
        # 断言 argsort 对二维数组 arr_2d 的操作会产生 MaskedArrayFutureWarning 警告
        result = assert_warns(
            np.ma.core.MaskedArrayFutureWarning, argsort, arr_2d)
        # 断言返回的结果与对 arr_2d 执行 axis=None 的 argsort 结果相等
        assert_equal(result, argsort(arr_2d, axis=None))

        # 对于显式指定的操作,不应产生警告
        argsort(arr_2d, axis=None)
        argsort(arr_2d, axis=-1)

    # 测试对 ndarray 类型执行 argsort 方法
    def test_function_ndarray(self):
        return self._test_base(np.ma.argsort, np.ndarray)

    # 测试对 maskedarray 类型执行 argsort 方法
    def test_function_maskedarray(self):
        return self._test_base(np.ma.argsort, np.ma.MaskedArray)

    # 测试对 maskedarray 类型的实例对象执行 argsort 方法
    def test_method(self):
        return self._test_base(np.ma.MaskedArray.argsort, np.ma.MaskedArray)


# 定义一个名为 TestMinimumMaximum 的测试类
class TestMinimumMaximum:

    # 测试 axis 默认值的情况
    def test_axis_default(self):
        # NumPy 版本 1.13,发布日期 2017-05-06

        # 创建一个一维的 masked 数组
        data1d = np.ma.arange(6)
        # 将一维数组重塑为二维数组
        data2d = data1d.reshape(2, 3)

        # 获取 np.ma.minimum.reduce 和 np.ma.maximum.reduce 函数的别名
        ma_min = np.ma.minimum.reduce
        ma_max = np.ma.maximum.reduce

        # 检查默认 axis 仍然为 None,在二维数组上会产生警告
        result = assert_warns(MaskedArrayFutureWarning, ma_max, data2d)
        assert_equal(result, ma_max(data2d, axis=None))

        result = assert_warns(MaskedArrayFutureWarning, ma_min, data2d)
        assert_equal(result, ma_min(data2d, axis=None))

        # 在一维数组上不应产生警告,因为新旧默认值等效
        result = ma_min(data1d)
        assert_equal(result, ma_min(data1d, axis=None))
        assert_equal(result, ma_min(data1d, axis=0))

        result = ma_max(data1d)
        assert_equal(result, ma_max(data1d, axis=None))
        assert_equal(result, ma_max(data1d, axis=0))


# 定义一个名为 TestFromtextfile 的测试类
class TestFromtextfile:
    # 测试 fromtextfile 方法的分隔符参数
    def test_fromtextfile_delimitor(self):
        # NumPy 版本 1.22.0,发布日期 2021-09-23

        # 创建一个 StringIO 对象,包含指定格式的文本内容
        textfile = io.StringIO(textwrap.dedent(
            """
            A,B,C,D
            'string 1';1;1.0;'mixed column'
            'string 2';2;2.0;
            'string 3';3;3.0;123
            'string 4';4;4.0;3.14
            """
        ))

        # 使用 pytest.warns 检查 DeprecationWarning 警告
        with pytest.warns(DeprecationWarning):
            # 调用 np.ma.mrecords.fromtextfile 方法,指定 delimitor 参数为 ';'
            result = np.ma.mrecords.fromtextfile(textfile, delimitor=';')

.\numpy\numpy\ma\tests\test_extras.py

# pylint: disable-msg=W0611, W0612, W0511
"""
Tests suite for MaskedArray.
Adapted from the original test_ma by Pierre Gerard-Marchant

:author: Pierre Gerard-Marchant
:contact: pierregm_at_uga_dot_edu
:version: $Id: test_extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $

"""
# 导入警告模块
import warnings
# 导入 itertools 模块
import itertools
# 导入 pytest 测试框架
import pytest

# 导入 NumPy 库,并从核心部分导入数值相关函数和类
import numpy as np
from numpy._core.numeric import normalize_axis_tuple
# 从 NumPy 测试模块中导入函数和类
from numpy.testing import (
    assert_warns, suppress_warnings
    )
# 从 NumPy 掩码数组测试工具模块中导入函数和类
from numpy.ma.testutils import (
    assert_, assert_array_equal, assert_equal, assert_almost_equal
    )
# 从 NumPy 掩码核心模块中导入函数和类
from numpy.ma.core import (
    array, arange, masked, MaskedArray, masked_array, getmaskarray, shape,
    nomask, ones, zeros, count
    )
# 从 NumPy 掩码额外工具模块中导入函数和类
from numpy.ma.extras import (
    atleast_1d, atleast_2d, atleast_3d, mr_, dot, polyfit, cov, corrcoef,
    median, average, unique, setxor1d, setdiff1d, union1d, intersect1d, in1d,
    ediff1d, apply_over_axes, apply_along_axis, compress_nd, compress_rowcols,
    mask_rowcols, clump_masked, clump_unmasked, flatnotmasked_contiguous,
    notmasked_contiguous, notmasked_edges, masked_all, masked_all_like, isin,
    diagflat, ndenumerate, stack, vstack, _covhelper
    )


class TestGeneric:
    # 测试 masked_all 函数
    def test_masked_all(self):
        # Tests masked_all
        # Standard dtype
        # 测试标准数据类型
        test = masked_all((2,), dtype=float)
        control = array([1, 1], mask=[1, 1], dtype=float)
        assert_equal(test, control)
        
        # Flexible dtype
        # 测试灵活数据类型
        dt = np.dtype({'names': ['a', 'b'], 'formats': ['f', 'f']})
        test = masked_all((2,), dtype=dt)
        control = array([(0, 0), (0, 0)], mask=[(1, 1), (1, 1)], dtype=dt)
        assert_equal(test, control)
        
        test = masked_all((2, 2), dtype=dt)
        control = array([[(0, 0), (0, 0)], [(0, 0), (0, 0)]],
                        mask=[[(1, 1), (1, 1)], [(1, 1), (1, 1)]],
                        dtype=dt)
        assert_equal(test, control)
        
        # Nested dtype
        # 测试嵌套数据类型
        dt = np.dtype([('a', 'f'), ('b', [('ba', 'f'), ('bb', 'f')])])
        test = masked_all((2,), dtype=dt)
        control = array([(1, (1, 1)), (1, (1, 1))],
                        mask=[(1, (1, 1)), (1, (1, 1))], dtype=dt)
        assert_equal(test, control)
        
        test = masked_all((1, 1), dtype=dt)
        control = array([[(1, (1, 1))]], mask=[[(1, (1, 1))]], dtype=dt)
        assert_equal(test, control)
    def test_masked_all_with_object_nested(self):
        # Test masked_all works with nested array with dtype of an 'object'
        # refers to issue #15895
        
        # 定义一个自定义的数据类型,包含一个嵌套数组 'c',整体形状为 (1,)
        my_dtype = np.dtype([('b', ([('c', object)], (1,)))])
        
        # 创建一个形状为 (1,) 的 masked array,使用上面定义的数据类型
        masked_arr = np.ma.masked_all((1,), my_dtype)

        # 断言 'masked_arr['b']' 的类型为 MaskedArray 对象
        assert_equal(type(masked_arr['b']), np.ma.core.MaskedArray)
        
        # 断言 'masked_arr['b']['c']' 的类型为 MaskedArray 对象
        assert_equal(type(masked_arr['b']['c']), np.ma.core.MaskedArray)
        
        # 断言 'masked_arr['b']['c']' 的长度为 1
        assert_equal(len(masked_arr['b']['c']), 1)
        
        # 断言 'masked_arr['b']['c']' 的形状为 (1, 1)
        assert_equal(masked_arr['b']['c'].shape, (1, 1))
        
        # 断言 'masked_arr['b']['c']._fill_value' 的形状为空元组 ()
        assert_equal(masked_arr['b']['c']._fill_value.shape, ())

    def test_masked_all_with_object(self):
        # same as above except that the array is not nested
        # 与上面相同,不过这次数组不是嵌套的
        
        # 定义一个自定义的数据类型,包含一个形状为 (1,) 的 object 类型数组 'b'
        my_dtype = np.dtype([('b', (object, (1,)))])
        
        # 创建一个形状为 (1,) 的 masked array,使用上面定义的数据类型
        masked_arr = np.ma.masked_all((1,), my_dtype)

        # 断言 'masked_arr['b']' 的类型为 MaskedArray 对象
        assert_equal(type(masked_arr['b']), np.ma.core.MaskedArray)
        
        # 断言 'masked_arr['b']' 的长度为 1
        assert_equal(len(masked_arr['b']), 1)
        
        # 断言 'masked_arr['b']' 的形状为 (1, 1)
        assert_equal(masked_arr['b'].shape, (1, 1))
        
        # 断言 'masked_arr['b']._fill_value' 的形状为空元组 ()
        assert_equal(masked_arr['b']._fill_value.shape, ())

    def test_masked_all_like(self):
        # Tests masked_all
        # Standard dtype
        
        # 创建一个标准的 float 类型数组 base
        base = array([1, 2], dtype=float)
        
        # 使用 masked_all_like 创建一个与 base 相同形状的 masked array test
        test = masked_all_like(base)
        
        # 创建一个标准的 float 类型数组 control,其中元素为 1,且所有元素都被 mask 掉
        control = array([1, 1], mask=[1, 1], dtype=float)
        
        # 断言 test 和 control 相等
        assert_equal(test, control)
        
        # Flexible dtype
        
        # 定义一个灵活的数据类型 dt,包含两个字段 'a' 和 'b',类型都是 float
        dt = np.dtype({'names': ['a', 'b'], 'formats': ['f', 'f']})
        
        # 创建一个与 control 形状相同的 masked array,使用上面定义的数据类型 dt
        test = masked_all_like(control, dtype=dt)
        
        # 断言 test 和 control 相等
        assert_equal(test, control)
        
        # Nested dtype
        
        # 定义一个嵌套的数据类型 dt,包含一个字段 'a' 类型为 float,和一个嵌套的数组 'b',包含两个字段 'ba' 和 'bb',类型都是 float
        dt = np.dtype([('a', 'f'), ('b', [('ba', 'f'), ('bb', 'f')])])
        
        # 创建一个与 control 形状相同的 masked array,使用上面定义的数据类型 dt
        test = masked_all_like(control, dtype=dt)
        
        # 断言 test 和 control 相等
        assert_equal(test, control)

    def check_clump(self, f):
        # 检查 clump 函数的功能
        
        # 对于范围从 1 到 6 的每一个整数 i
        for i in range(1, 7):
            # 对于范围从 0 到 2^i - 1 的每一个整数 j
            for j in range(2**i):
                # 创建一个长度为 i 的整数数组 k
                k = np.arange(i, dtype=int)
                
                # 创建一个长度为 i,填充为 j 的整数数组 ja
                ja = np.full(i, j, dtype=int)
                
                # 创建一个长度为 2^i 的 masked array a,其中元素为 2 的 k 次方
                a = masked_array(2**k)
                
                # 设置 a 的 mask,使得只保留 ja & (2**k) != 0 的元素
                a.mask = (ja & (2**k)) != 0
                
                # 初始化变量 s 为 0
                s = 0
                
                # 对于 f(a) 返回的每一个 slice sl
                for sl in f(a):
                    # 将 a 中 sl 对应的数据元素求和并加到 s 上
                    s += a.data[sl].sum()
                
                # 如果 f 是 clump_unmasked 函数,则断言压缩后的 a 的总和等于 s
                if f == clump_unmasked:
                    assert_equal(a.compressed().sum(), s)
                else:
                    # 否则,反转 a 的 mask,并断言压缩后的 a 的总和等于 s
                    a.mask = ~a.mask
                    assert_equal(a.compressed().sum(), s)

    def test_clump_masked(self):
        # Test clump_masked
        
        # 创建一个包含 0 到 9 的整数的 masked array a
        a = masked_array(np.arange(10))
        
        # 将索引为 [0, 1, 2, 6, 8, 9] 的元素设为 masked
        a[[0, 1, 2, 6, 8, 9]] = masked
        
        # 调用 clump_masked 函数,返回的结果 test 应与 control 相等
        test = clump_masked(a)
        control = [slice(0, 3), slice(6, 7), slice(8, 10)]
        assert_equal(test, control)
        
        # 调用 self.check_clump 函数,检查 clump_masked 函数的功能
        self.check_clump(clump_masked)
    # 定义一个测试方法 test_clump_unmasked,用于测试 clump_unmasked 函数
    def test_clump_unmasked(self):
        # 创建一个包含遮盖数组的 masked_array,数组范围为0到9
        a = masked_array(np.arange(10))
        # 将指定索引处的元素标记为 masked(遮盖)
        a[[0, 1, 2, 6, 8, 9]] = masked
        # 调用 clump_unmasked 函数,获取结果
        test = clump_unmasked(a)
        # 期望的结果
        control = [slice(3, 6), slice(7, 8), ]
        # 断言测试结果与期望结果相等
        assert_equal(test, control)

        # 调用 self.check_clump 方法,验证 clump_unmasked 函数的其他方面

    # 定义一个测试方法 test_flatnotmasked_contiguous,用于测试 flatnotmasked_contiguous 函数
    def test_flatnotmasked_contiguous(self):
        # 创建一个包含整数0到9的数组 a
        a = arange(10)
        # 对没有遮盖的情况进行测试,预期得到包含一个完整范围的切片
        test = flatnotmasked_contiguous(a)
        assert_equal(test, [slice(0, a.size)])

        # 将数组 a 的遮盖设置为全为 False 的情况进行测试
        a.mask = np.zeros(10, dtype=bool)
        assert_equal(test, [slice(0, a.size)])

        # 对包含部分遮盖的情况进行测试
        a[(a < 3) | (a > 8) | (a == 5)] = masked
        test = flatnotmasked_contiguous(a)
        assert_equal(test, [slice(3, 5), slice(6, 9)])

        # 将数组 a 的所有元素标记为遮盖,并进行测试
        a[:] = masked
        test = flatnotmasked_contiguous(a)
        # 预期返回空列表,因为没有非遮盖的连续区域
        assert_equal(test, [])
class TestAverage:
    # Several tests of average. Why so many ? Good point...
    # 定义一个测试类 TestAverage,用于测试 average 函数,包含多个测试用例

    def test_testAverage1(self):
        # Test of average.
        # 测试 average 函数的基本用例
        ott = array([0., 1., 2., 3.], mask=[True, False, False, False])
        # 创建一个带遮罩的数组 ott,其中第一个元素被遮罩
        assert_equal(2.0, average(ott, axis=0))
        # 断言计算 ott 数组沿着 axis=0 的平均值为 2.0
        assert_equal(2.0, average(ott, weights=[1., 1., 2., 1.]))
        # 断言计算 ott 数组使用权重 [1., 1., 2., 1.] 的加权平均值为 2.0
        result, wts = average(ott, weights=[1., 1., 2., 1.], returned=True)
        # 计算 ott 数组使用权重 [1., 1., 2., 1.] 的加权平均值,并返回结果和权重
        assert_equal(2.0, result)
        # 断言计算结果为 2.0
        assert_(wts == 4.0)
        # 断言权重为 4.0
        ott[:] = masked
        # 将 ott 数组全部遮罩
        assert_equal(average(ott, axis=0).mask, [True])
        # 断言计算遮罩后 ott 数组沿着 axis=0 的平均值的遮罩为 [True]
        ott = array([0., 1., 2., 3.], mask=[True, False, False, False])
        # 重新初始化 ott 数组
        ott = ott.reshape(2, 2)
        # 将 ott 数组重塑为 2x2 的形状
        ott[:, 1] = masked
        # 将 ott 数组第二列遮罩
        assert_equal(average(ott, axis=0), [2.0, 0.0])
        # 断言计算 ott 数组沿着 axis=0 的平均值为 [2.0, 0.0]
        assert_equal(average(ott, axis=1).mask[0], [True])
        # 断言计算 ott 数组沿着 axis=1 的平均值的遮罩第一个元素为 [True]
        assert_equal([2., 0.], average(ott, axis=0))
        # 断言计算 ott 数组沿着 axis=0 的平均值为 [2., 0.]
        result, wts = average(ott, axis=0, returned=True)
        # 计算 ott 数组沿着 axis=0 的平均值,并返回结果和权重
        assert_equal(wts, [1., 0.])
        # 断言权重为 [1., 0.]

    def test_testAverage2(self):
        # More tests of average.
        # 更多 average 函数的测试用例
        w1 = [0, 1, 1, 1, 1, 0]
        # 定义权重数组 w1
        w2 = [[0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 0, 1]]
        # 定义权重数组 w2
        x = arange(6, dtype=np.float64)
        # 创建一个浮点型数组 x,包含 0 到 5 的值
        assert_equal(average(x, axis=0), 2.5)
        # 断言计算 x 数组沿着 axis=0 的平均值为 2.5
        assert_equal(average(x, axis=0, weights=w1), 2.5)
        # 断言计算 x 数组使用权重 w1 的加权平均值为 2.5
        y = array([arange(6, dtype=np.float64), 2.0 * arange(6)])
        # 创建一个包含两行的浮点型数组 y,第一行是 0 到 5 的值,第二行是第一行值的两倍
        assert_equal(average(y, None), np.add.reduce(np.arange(6)) * 3. / 12.)
        # 断言计算 y 数组的平均值,未指定 axis,计算全局平均值
        assert_equal(average(y, axis=0), np.arange(6) * 3. / 2.)
        # 断言计算 y 数组沿着 axis=0 的平均值
        assert_equal(average(y, axis=1),
                     [average(x, axis=0), average(x, axis=0) * 2.0])
        # 断言计算 y 数组沿着 axis=1 的平均值
        assert_equal(average(y, None, weights=w2), 20. / 6.)
        # 断言计算 y 数组的平均值,未指定 axis,使用权重 w2
        assert_equal(average(y, axis=0, weights=w2),
                     [0., 1., 2., 3., 4., 10.])
        # 断言计算 y 数组沿着 axis=0 的平均值,使用权重 w2
        assert_equal(average(y, axis=1),
                     [average(x, axis=0), average(x, axis=0) * 2.0])
        # 断言计算 y 数组沿着 axis=1 的平均值
        m1 = zeros(6)
        # 创建一个长度为 6 的零数组 m1
        m2 = [0, 0, 1, 1, 0, 0]
        # 定义一个长度为 6 的数组 m2,部分元素被置为 1
        m3 = [[0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0]]
        # 定义一个包含两行的数组 m3,每行有一些元素被置为 1
        m4 = ones(6)
        # 创建一个长度为 6 的元素全为 1 的数组 m4
        m5 = [0, 1, 1, 1, 1, 1]
        # 定义一个长度为 6 的数组 m5,除了第一个元素外,所有元素都被置为 1
        assert_equal(average(masked_array(x, m1), axis=0), 2.5)
        # 断言计算被遮罩的 x 数组沿着 axis=0 的平均值为 2.5
        assert_equal(average(masked_array(x, m2), axis=0), 2.5)
        # 断言计算被遮罩的 x 数组(使用 m2 遮罩)沿着 axis=0 的平均值为 2.5
        assert_equal(average(masked_array(x, m4), axis=0).mask, [True])
        # 断言计算被遮罩的 x 数组(使用 m4 遮罩)沿着 axis=0 的平均值的遮罩为 [True]
        assert_equal(average(masked_array(x, m5), axis=0), 0.0)
        # 断言计算被遮罩的 x 数组(使用 m5 遮罩)沿着 axis=0 的平均值为 0.0
        assert_equal(count(average(masked_array(x, m4), axis=0)), 0)
        # 断言计算被遮罩的 x 数组(使用 m4 遮罩)沿着 axis=0 的平均值的元素数量为 0
        z = masked_array(y, m3)
        # 创建一个使用 m3 遮罩的 y 数组 z
        assert_equal(average(z, None), 20. / 6.)
        # 断言计算被遮罩的 y 数组 z 的平均值,未指定 axis
        assert_equal(average(z, axis=0), [0., 1., 99., 99., 4.0, 7.5])
        # 断言计算被遮罩的 y 数组 z 沿
    def test_testAverage3(self):
        # 测试 average 函数的更多用例
        # 创建数组 a 和 b,分别为 [0, 1, 2, 3, 4, 5] 和 [0, 3, 6, 9, 12, 15]
        a = arange(6)
        b = arange(6) * 3
        # 计算在 axis=1 上的加权平均,返回结果 r1 和权重 w1
        r1, w1 = average([[a, b], [b, a]], axis=1, returned=True)
        # 断言 r1 和 w1 的形状相等
        assert_equal(shape(r1), shape(w1))
        # 再次断言 r1 和 w1 的形状相等
        assert_equal(r1.shape, w1.shape)
        # 计算在 axis=0 上的加权平均,weights=[3, 1],返回结果 r2 和权重 w2
        r2, w2 = average(ones((2, 2, 3)), axis=0, weights=[3, 1], returned=True)
        # 断言 w2 和 r2 的形状相等
        assert_equal(shape(w2), shape(r2))
        # 计算在 axis=None 上的平均值,返回结果 r2 和权重 w2
        r2, w2 = average(ones((2, 2, 3)), returned=True)
        # 断言 w2 和 r2 的形状相等
        assert_equal(shape(w2), shape(r2))
        # 计算在 axis=None 上的加权平均,weights 全为 1,返回结果 r2 和权重 w2
        r2, w2 = average(ones((2, 2, 3)), weights=ones((2, 2, 3)), returned=True)
        # 断言 w2 和 r2 的形状相等
        assert_equal(shape(w2), shape(r2))
        # 创建二维数组 a2d,[[1.0, 2.0], [0.0, 4.0]]
        a2d = array([[1, 2], [0, 4]], float)
        # 创建掩码数组 a2dm,[[False, False], [True, False]]
        a2dm = masked_array(a2d, [[False, False], [True, False]])
        # 计算在 axis=0 上的平均值,返回结果 a2da,应为 [0.5, 3.0]
        a2da = average(a2d, axis=0)
        # 断言 a2da 的结果符合预期 [0.5, 3.0]
        assert_equal(a2da, [0.5, 3.0])
        # 计算在 axis=0 上的掩码数组平均值,返回结果 a2dma,应为 [1.0, 3.0]
        a2dma = average(a2dm, axis=0)
        # 断言 a2dma 的结果符合预期 [1.0, 3.0]
        assert_equal(a2dma, [1.0, 3.0])
        # 计算在 axis=None 上的掩码数组平均值,返回结果 a2dma,应为 7. / 3.
        a2dma = average(a2dm, axis=None)
        # 断言 a2dma 的结果符合预期 7. / 3.
        assert_equal(a2dma, 7. / 3.)
        # 计算在 axis=1 上的掩码数组平均值,返回结果 a2dma,应为 [1.5, 4.0]
        a2dma = average(a2dm, axis=1)
        # 断言 a2dma 的结果符合预期 [1.5, 4.0]

    def test_testAverage4(self):
        # 测试 average 函数中 keepdims 参数的工作情况
        # 创建数组 x,形状为 (3, 1),[[2], [3], [4]]
        x = np.array([2, 3, 4]).reshape(3, 1)
        # 创建掩码数组 b,形状同 x,[[2], [3], [--]]
        b = np.ma.array(x, mask=[[False], [False], [True]])
        # 创建权重数组 w,形状为 (3, 1),[[4], [5], [6]]
        w = np.array([4, 5, 6]).reshape(3, 1)
        # 计算在 axis=1 上的加权平均,返回结果 actual,应为 [[2.], [3.], [4.]]
        actual = average(b, weights=w, axis=1, keepdims=True)
        # 创建掩码数组 desired,形状同 actual,[[2.], [3.], [--]]
        desired = masked_array([[2.], [3.], [4.]], [[False], [False], [True]])
        # 断言 actual 和 desired 的结果相等
        assert_equal(actual, desired)
    # 定义一个测试方法,用于测试权重和输入维度不同的情况
    def test_weight_and_input_dims_different(self):
        # 模仿 np.average() 函数在 lib/test/test_function_base.py 中的测试
        # 创建一个形状为 (2, 2, 3) 的三维数组 y,包含从 0 到 11 的连续整数
        y = np.arange(12).reshape(2, 2, 3)
        # 创建一个形状为 (2, 2, 3) 的三维数组 w,包含特定的权重值
        w = np.array([0., 0., 1., .5, .5, 0., 0., .5, .5, 1., 0., 0.])\
            .reshape(2, 2, 3)

        # 创建一个形状为 (2, 2, 3) 的布尔数组 m,全为 False,用于创建掩码
        m = np.full((2, 2, 3), False)
        # 将 y 封装成一个带掩码的 masked array 对象 yma
        yma = np.ma.array(y, mask=m)
        # 获取 w 的第一个轴上的切片,形状为 (2, 2)
        subw0 = w[:, :, 0]

        # 计算使用 subw0 权重的 yma 的平均值,沿着第 0 和第 1 轴
        actual = average(yma, axis=(0, 1), weights=subw0)
        # 期望的结果,带有掩码
        desired = masked_array([7., 8., 9.], mask=[False, False, False])
        # 断言计算结果与期望结果的近似性
        assert_almost_equal(actual, desired)

        # 更新 m 的掩码设置
        m = np.full((2, 2, 3), False)
        m[:, :, 0] = True
        m[0, 0, 1] = True
        yma = np.ma.array(y, mask=m)
        # 重新计算带有更新掩码的 yma 的平均值
        actual = average(yma, axis=(0, 1), weights=subw0)
        # 更新的期望结果,带有更新的掩码
        desired = masked_array(
            [np.nan, 8., 9.],
            mask=[True, False, False])
        # 断言计算结果与期望结果的近似性
        assert_almost_equal(actual, desired)

        # 重置 m 的掩码设置
        m = np.full((2, 2, 3), False)
        yma = np.ma.array(y, mask=m)

        # 获取 w 的第二个轴上的切片,形状为 (2, 3)
        subw1 = w[1, :, :]
        # 计算使用 subw1 权重的 yma 的平均值,沿着第 1 和第 2 轴
        actual = average(yma, axis=(1, 2), weights=subw1)
        # 期望的结果,带有掩码
        desired = masked_array([2.25, 8.25], mask=[False, False])
        # 断言计算结果与期望结果的近似性
        assert_almost_equal(actual, desired)

        # 当权重的形状与指定的轴不匹配时,抛出 ValueError 异常
        with pytest.raises(
                ValueError,
                match="Shape of weights must be consistent with "
                      "shape of a along specified axis"):
            average(yma, axis=(0, 1, 2), weights=subw0)

        with pytest.raises(
                ValueError,
                match="Shape of weights must be consistent with "
                      "shape of a along specified axis"):
            average(yma, axis=(0, 1), weights=subw1)

        # 当交换轴时,使用 (1, 0) 轴的平均值应该等同于使用转置后的权重 subw0.T
        actual = average(yma, axis=(1, 0), weights=subw0)
        desired = average(yma, axis=(0, 1), weights=subw0.T)
        # 断言计算结果与期望结果的近似性
        assert_almost_equal(actual, desired)

    def test_onintegers_with_mask(self):
        # 测试带有掩码的整数数组的平均值计算
        a = average(array([1, 2]))
        # 断言计算结果与期望结果相等
        assert_equal(a, 1.5)
        a = average(array([1, 2, 3, 4], mask=[False, False, True, True]))
        # 断言计算结果与期望结果相等
        assert_equal(a, 1.5)
    def test_complex(self):
        # 测试复杂数据情况。
        # (针对 https://github.com/numpy/numpy/issues/2684 的回归测试)

        # 创建一个布尔掩码数组
        mask = np.array([[0, 0, 0, 1, 0],
                         [0, 1, 0, 0, 0]], dtype=bool)
        
        # 创建一个带掩码的复数数组
        a = masked_array([[0, 1+2j, 3+4j, 5+6j, 7+8j],
                          [9j, 0+1j, 2+3j, 4+5j, 7+7j]],
                         mask=mask)

        # 计算数组 a 的平均值
        av = average(a)
        # 计算压缩后数组 a 的平均值,并进行近似相等性断言
        expected = np.average(a.compressed())
        assert_almost_equal(av.real, expected.real)
        assert_almost_equal(av.imag, expected.imag)

        # 沿着 axis=0 计算数组 a 的平均值
        av0 = average(a, axis=0)
        # 计算实部和虚部的加权平均值,并进行近似相等性断言
        expected0 = average(a.real, axis=0) + average(a.imag, axis=0)*1j
        assert_almost_equal(av0.real, expected0.real)
        assert_almost_equal(av0.imag, expected0.imag)

        # 沿着 axis=1 计算数组 a 的平均值
        av1 = average(a, axis=1)
        # 计算实部和虚部的加权平均值,并进行近似相等性断言
        expected1 = average(a.real, axis=1) + average(a.imag, axis=1)*1j
        assert_almost_equal(av1.real, expected1.real)
        assert_almost_equal(av1.imag, expected1.imag)

        # 测试带有 'weights' 参数的情况
        wts = np.array([[0.5, 1.0, 2.0, 1.0, 0.5],
                        [1.0, 1.0, 1.0, 1.0, 1.0]])
        
        # 使用权重计算数组 a 的加权平均值
        wav = average(a, weights=wts)
        # 计算压缩后数组 a 的加权平均值,并进行近似相等性断言
        expected = np.average(a.compressed(), weights=wts[~mask])
        assert_almost_equal(wav.real, expected.real)
        assert_almost_equal(wav.imag, expected.imag)

        # 沿着 axis=0 使用权重计算数组 a 的加权平均值
        wav0 = average(a, weights=wts, axis=0)
        # 计算实部和虚部的加权平均值,并进行近似相等性断言
        expected0 = (average(a.real, weights=wts, axis=0) +
                     average(a.imag, weights=wts, axis=0)*1j)
        assert_almost_equal(wav0.real, expected0.real)
        assert_almost_equal(wav0.imag, expected0.imag)

        # 沿着 axis=1 使用权重计算数组 a 的加权平均值
        wav1 = average(a, weights=wts, axis=1)
        # 计算实部和虚部的加权平均值,并进行近似相等性断言
        expected1 = (average(a.real, weights=wts, axis=1) +
                     average(a.imag, weights=wts, axis=1)*1j)
        assert_almost_equal(wav1.real, expected1.real)
        assert_almost_equal(wav1.imag, expected1.imag)

    @pytest.mark.parametrize(
        'x, axis, expected_avg, weights, expected_wavg, expected_wsum',
        [([1, 2, 3], None, [2.0], [3, 4, 1], [1.75], [8.0]),
         ([[1, 2, 5], [1, 6, 11]], 0, [[1.0, 4.0, 8.0]],
          [1, 3], [[1.0, 5.0, 9.5]], [[4, 4, 4]])],
    )
    def test_basic_keepdims(self, x, axis, expected_avg,
                            weights, expected_wavg, expected_wsum):
        # 测试带有 keepdims=True 的基本情况

        # 计算数组 x 的平均值,并进行形状相等性断言
        avg = np.ma.average(x, axis=axis, keepdims=True)
        assert avg.shape == np.shape(expected_avg)
        assert_array_equal(avg, expected_avg)

        # 使用权重计算数组 x 的加权平均值,并进行形状相等性断言
        wavg = np.ma.average(x, axis=axis, weights=weights, keepdims=True)
        assert wavg.shape == np.shape(expected_wavg)
        assert_array_equal(wavg, expected_wavg)

        # 使用权重计算数组 x 的加权平均值和加权和,并进行形状相等性断言
        wavg, wsum = np.ma.average(x, axis=axis, weights=weights,
                                   returned=True, keepdims=True)
        assert wavg.shape == np.shape(expected_wavg)
        assert_array_equal(wavg, expected_wavg)
        assert wsum.shape == np.shape(expected_wsum)
        assert_array_equal(wsum, expected_wsum)
    # 定义一个测试方法,用于测试带有掩码权重的情况
    def test_masked_weights(self):
        # 使用掩码数组创建一个掩码数组对象 a,形状为 3x3
        a = np.ma.array(np.arange(9).reshape(3, 3),
                        mask=[[1, 0, 0], [1, 0, 0], [0, 0, 0]])
        
        # 创建未掩码的权重数组对象 weights_unmasked
        weights_unmasked = masked_array([5, 28, 31], mask=False)
        
        # 创建带有掩码的权重数组对象 weights_masked
        weights_masked = masked_array([5, 28, 31], mask=[1, 0, 0])

        # 计算未掩码情况下的平均值,沿着 axis=0 方向,使用权重 weights_unmasked,不返回权重
        avg_unmasked = average(a, axis=0,
                               weights=weights_unmasked, returned=False)
        # 预期的未掩码情况下的平均值
        expected_unmasked = np.array([6.0, 5.21875, 6.21875])
        # 断言计算结果与预期结果的接近程度
        assert_almost_equal(avg_unmasked, expected_unmasked)

        # 计算带有掩码情况下的平均值,沿着 axis=0 方向,使用权重 weights_masked,不返回权重
        avg_masked = average(a, axis=0, weights=weights_masked, returned=False)
        # 预期的带有掩码情况下的平均值
        expected_masked = np.array([6.0, 5.576271186440678, 6.576271186440678])
        # 断言计算结果与预期结果的接近程度
        assert_almost_equal(avg_masked, expected_masked)

        # weights 如果需要的话应该被掩码,这取决于数组的掩码情况。
        # 这是为了避免对被掩码的 NaN 或其他值求和,这些值不会被零取消
        a = np.ma.array([1.0,   2.0,   3.0,  4.0],
                   mask=[False, False, True, True])
        
        # 计算未掩码情况下的平均值,使用权重 [1, 1, 1, np.nan]
        avg_unmasked = average(a, weights=[1, 1, 1, np.nan])
        # 断言计算结果与预期的 1.5 的接近程度
        assert_almost_equal(avg_unmasked, 1.5)

        # 创建一个 3x4 的掩码数组对象 a,其中包含了掩码
        a = np.ma.array([
            [1.0, 2.0, 3.0, 4.0],
            [5.0, 6.0, 7.0, 8.0],
            [9.0, 1.0, 2.0, 3.0],
        ], mask=[
            [False, True, True, False],
            [True, False, True, True],
            [True, False, True, False],
        ])
        
        # 沿着 axis=0 方向计算带有掩码的平均值,使用权重 [1, np.nan, 1]
        avg_masked = np.ma.average(a, weights=[1, np.nan, 1], axis=0)
        # 预期的带有掩码的平均值数组
        avg_expected = np.ma.array([1.0, np.nan, np.nan, 3.5],
                              mask=[False, True, True, False])
        
        # 断言计算结果与预期结果的接近程度
        assert_almost_equal(avg_masked, avg_expected)
        # 断言掩码数组的掩码情况是否与预期一致
        assert_equal(avg_masked.mask, avg_expected.mask)
class TestConcatenator:
    # Tests for mr_, the equivalent of r_ for masked arrays.

    def test_1d(self):
        # Tests mr_ on 1D arrays.
        assert_array_equal(mr_[1, 2, 3, 4, 5, 6], array([1, 2, 3, 4, 5, 6]))
        b = ones(5)
        m = [1, 0, 0, 0, 0]
        d = masked_array(b, mask=m)
        # Concatenate masked arrays and plain values using mr_
        c = mr_[d, 0, 0, d]
        assert_(isinstance(c, MaskedArray))
        assert_array_equal(c, [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1])
        assert_array_equal(c.mask, mr_[m, 0, 0, m])

    def test_2d(self):
        # Tests mr_ on 2D arrays.
        a_1 = np.random.rand(5, 5)
        a_2 = np.random.rand(5, 5)
        m_1 = np.round(np.random.rand(5, 5), 0)
        m_2 = np.round(np.random.rand(5, 5), 0)
        b_1 = masked_array(a_1, mask=m_1)
        b_2 = masked_array(a_2, mask=m_2)
        # Append columns using mr_
        d = mr_['1', b_1, b_2]
        assert_(d.shape == (5, 10))
        assert_array_equal(d[:, :5], b_1)
        assert_array_equal(d[:, 5:], b_2)
        assert_array_equal(d.mask, np.r_['1', m_1, m_2])
        d = mr_[b_1, b_2]
        assert_(d.shape == (10, 5))
        assert_array_equal(d[:5,:], b_1)
        assert_array_equal(d[5:,:], b_2)
        assert_array_equal(d.mask, np.r_[m_1, m_2])

    def test_masked_constant(self):
        # Tests mr_ with masked constants.
        actual = mr_[np.ma.masked, 1]
        assert_equal(actual.mask, [True, False])
        assert_equal(actual.data[1], 1)

        actual = mr_[[1, 2], np.ma.masked]
        assert_equal(actual.mask, [False, False, True])
        assert_equal(actual.data[:2], [1, 2])


class TestNotMasked:
    # Tests notmasked_edges and notmasked_contiguous.
    def test_edges(self):
        # Tests unmasked_edges
        # 创建一个 5x5 的 NumPy 掩码数组
        data = masked_array(np.arange(25).reshape(5, 5),
                            mask=[[0, 0, 1, 0, 0],
                                  [0, 0, 0, 1, 1],
                                  [1, 1, 0, 0, 0],
                                  [0, 0, 0, 0, 0],
                                  [1, 1, 1, 0, 0]],)
        # 调用 notmasked_edges 函数,测试不同的参数
        test = notmasked_edges(data, None)
        # 断言测试结果与预期结果一致
        assert_equal(test, [0, 24])
        # 再次调用 notmasked_edges 函数,使用参数 0
        test = notmasked_edges(data, 0)
        # 断言第一个返回值与预期的列表一致
        assert_equal(test[0], [(0, 0, 1, 0, 0), (0, 1, 2, 3, 4)])
        # 断言第二个返回值与预期的列表一致
        assert_equal(test[1], [(3, 3, 3, 4, 4), (0, 1, 2, 3, 4)])
        # 再次调用 notmasked_edges 函数,使用参数 1
        test = notmasked_edges(data, 1)
        # 断言第一个返回值与预期的列表一致
        assert_equal(test[0], [(0, 1, 2, 3, 4), (0, 0, 2, 0, 3)])
        # 断言第二个返回值与预期的列表一致
        assert_equal(test[1], [(0, 1, 2, 3, 4), (4, 2, 4, 4, 4)])
        #
        # 将 data 的数据部分传递给 notmasked_edges 函数,测试不同的参数
        test = notmasked_edges(data.data, None)
        # 断言测试结果与预期结果一致
        assert_equal(test, [0, 24])
        # 再次调用 notmasked_edges 函数,使用参数 0
        test = notmasked_edges(data.data, 0)
        # 断言第一个返回值与预期的列表一致
        assert_equal(test[0], [(0, 0, 0, 0, 0), (0, 1, 2, 3, 4)])
        # 断言第二个返回值与预期的列表一致
        assert_equal(test[1], [(4, 4, 4, 4, 4), (0, 1, 2, 3, 4)])
        # 再次调用 notmasked_edges 函数,使用参数 -1
        test = notmasked_edges(data.data, -1)
        # 断言第一个返回值与预期的列表一致
        assert_equal(test[0], [(0, 1, 2, 3, 4), (0, 0, 0, 0, 0)])
        # 断言第二个返回值与预期的列表一致
        assert_equal(test[1], [(0, 1, 2, 3, 4), (4, 4, 4, 4, 4)])
        #
        # 修改 data 中的倒数第二行为 masked
        data[-2] = masked
        # 再次调用 notmasked_edges 函数,使用参数 0
        test = notmasked_edges(data, 0)
        # 断言第一个返回值与预期的列表一致
        assert_equal(test[0], [(0, 0, 1, 0, 0), (0, 1, 2, 3, 4)])
        # 断言第二个返回值与预期的列表一致
        assert_equal(test[1], [(1, 1, 2, 4, 4), (0, 1, 2, 3, 4)])
        # 再次调用 notmasked_edges 函数,使用参数 -1
        test = notmasked_edges(data, -1)
        # 断言第一个返回值与预期的列表一致
        assert_equal(test[0], [(0, 1, 2, 4), (0, 0, 2, 3)])
        # 断言第二个返回值与预期的列表一致
        assert_equal(test[1], [(0, 1, 2, 4), (4, 2, 4, 4)])

    def test_contiguous(self):
        # Tests notmasked_contiguous
        # 创建一个 3x8 的 NumPy 掩码数组
        a = masked_array(np.arange(24).reshape(3, 8),
                         mask=[[0, 0, 0, 0, 1, 1, 1, 1],
                               [1, 1, 1, 1, 1, 1, 1, 1],
                               [0, 0, 0, 0, 0, 0, 1, 0]])
        # 调用 notmasked_contiguous 函数,测试不同的参数
        tmp = notmasked_contiguous(a, None)
        # 断言测试结果与预期结果一致
        assert_equal(tmp, [
            slice(0, 4, None),
            slice(16, 22, None),
            slice(23, 24, None)
        ])

        # 再次调用 notmasked_contiguous 函数,使用参数 0
        tmp = notmasked_contiguous(a, 0)
        # 断言测试结果与预期结果一致
        assert_equal(tmp, [
            [slice(0, 1, None), slice(2, 3, None)],
            [slice(0, 1, None), slice(2, 3, None)],
            [slice(0, 1, None), slice(2, 3, None)],
            [slice(0, 1, None), slice(2, 3, None)],
            [slice(2, 3, None)],
            [slice(2, 3, None)],
            [],
            [slice(2, 3, None)]
        ])
        #
        # 再次调用 notmasked_contiguous 函数,使用参数 1
        tmp = notmasked_contiguous(a, 1)
        # 断言测试结果与预期结果一致
        assert_equal(tmp, [
            [slice(0, 4, None)],
            [],
            [slice(0, 6, None), slice(7, 8, None)]
        ])
# 定义一个测试类 TestCompressFunctions,用于测试压缩函数的功能
class TestCompressFunctions:

    # 定义测试方法 test_compress_rowcols,测试 compress_rowcols 函数
    def test_compress_rowcols(self):
        # 创建一个 3x3 的数组 x,内容为 0 到 8,其中部分元素被遮盖(masked)
        x = array(np.arange(9).reshape(3, 3),
                  mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]])
        # 断言调用 compress_rowcols(x) 后的结果与预期结果相等,验证行列压缩的功能
        assert_equal(compress_rowcols(x), [[4, 5], [7, 8]])
        # 断言调用 compress_rowcols(x, 0) 后的结果与预期结果相等,验证按行压缩的功能
        assert_equal(compress_rowcols(x, 0), [[3, 4, 5], [6, 7, 8]])
        # 断言调用 compress_rowcols(x, 1) 后的结果与预期结果相等,验证按列压缩的功能
        assert_equal(compress_rowcols(x, 1), [[1, 2], [4, 5], [7, 8]])
        
        # 修改 x 的数据内容和遮盖情况,进行下一组测试
        x = array(x._data, mask=[[0, 0, 0], [0, 1, 0], [0, 0, 0]])
        assert_equal(compress_rowcols(x), [[0, 2], [6, 8]])
        assert_equal(compress_rowcols(x, 0), [[0, 1, 2], [6, 7, 8]])
        assert_equal(compress_rowcols(x, 1), [[0, 2], [3, 5], [6, 8]])
        
        # 再次修改 x 的数据内容和遮盖情况,进行下一组测试
        x = array(x._data, mask=[[1, 0, 0], [0, 1, 0], [0, 0, 0]])
        assert_equal(compress_rowcols(x), [[8]])
        assert_equal(compress_rowcols(x, 0), [[6, 7, 8]])
        assert_equal(compress_rowcols(x, 1,), [[2], [5], [8]])
        
        # 最后修改 x 的数据内容和遮盖情况,进行最后一组测试
        x = array(x._data, mask=[[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        # 断言调用 compress_rowcols(x).size 后的结果为 0,验证空结果情况
        assert_equal(compress_rowcols(x).size, 0)
        assert_equal(compress_rowcols(x, 0).size, 0)
        assert_equal(compress_rowcols(x, 1).size, 0)

    # 定义测试方法 test_mask_rowcols,测试 mask_rowcols 函数
    def test_mask_rowcols(self):
        # 创建一个 3x3 的数组 x,内容为 0 到 8,其中部分元素被遮盖(masked)
        x = array(np.arange(9).reshape(3, 3),
                  mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]])
        # 断言调用 mask_rowcols(x) 后的 mask 结果与预期结果相等,验证行列遮盖的功能
        assert_equal(mask_rowcols(x).mask,
                     [[1, 1, 1], [1, 0, 0], [1, 0, 0]])
        # 断言调用 mask_rowcols(x, 0) 后的 mask 结果与预期结果相等,验证按行遮盖的功能
        assert_equal(mask_rowcols(x, 0).mask,
                     [[1, 1, 1], [0, 0, 0], [0, 0, 0]])
        # 断言调用 mask_rowcols(x, 1) 后的 mask 结果与预期结果相等,验证按列遮盖的功能
        assert_equal(mask_rowcols(x, 1).mask,
                     [[1, 0, 0], [1, 0, 0], [1, 0, 0]])
        
        # 修改 x 的数据内容和遮盖情况,进行下一组测试
        x = array(x._data, mask=[[0, 0, 0], [0, 1, 0], [0, 0, 0]])
        assert_equal(mask_rowcols(x).mask,
                     [[0, 1, 0], [1, 1, 1], [0, 1, 0]])
        assert_equal(mask_rowcols(x, 0).mask,
                     [[0, 0, 0], [1, 1, 1], [0, 0, 0]])
        assert_equal(mask_rowcols(x, 1).mask,
                     [[0, 1, 0], [0, 1, 0], [0, 1, 0]])
        
        # 再次修改 x 的数据内容和遮盖情况,进行下一组测试
        x = array(x._data, mask=[[1, 0, 0], [0, 1, 0], [0, 0, 0]])
        assert_equal(mask_rowcols(x).mask,
                     [[1, 1, 1], [1, 1, 1], [1, 1, 0]])
        assert_equal(mask_rowcols(x, 0).mask,
                     [[1, 1, 1], [1, 1, 1], [0, 0, 0]])
        assert_equal(mask_rowcols(x, 1,).mask,
                     [[1, 1, 0], [1, 1, 0], [1, 1, 0]])
        
        # 最后修改 x 的数据内容和遮盖情况,进行最后一组测试
        x = array(x._data, mask=[[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        # 断言调用 mask_rowcols(x).all() 后的结果为 masked,验证所有元素遮盖的情况
        assert_(mask_rowcols(x).all() is masked)
        assert_(mask_rowcols(x, 0).all() is masked)
        assert_(mask_rowcols(x, 1).all() is masked)
        # 断言调用 mask_rowcols(x).mask.all() 后的结果为 True,验证所有元素都被遮盖
        assert_(mask_rowcols(x).mask.all())
        assert_(mask_rowcols(x, 0).mask.all())
        assert_(mask_rowcols(x, 1).mask.all())

    # 使用 pytest 的参数化标记,对 func 和 rowcols_axis 参数进行参数化
    @pytest.mark.parametrize("axis", [None, 0, 1])
    @pytest.mark.parametrize(["func", "rowcols_axis"],
                             [(np.ma.mask_rows, 0), (np.ma.mask_cols, 1)])
    # 测试关于 `mask_rows` 和 `mask_cols` 函数中 axis 参数的弃用警告
    def test_mask_row_cols_axis_deprecation(self, axis, func, rowcols_axis):
        # 创建一个 3x3 的数组 x,并指定部分元素被遮盖(masked)
        x = array(np.arange(9).reshape(3, 3),
                  mask=[[1, 0, 0], [0, 0, 0], [0, 0, 0]])

        # 使用 assert_warns 确保在调用 func 函数时会出现 DeprecationWarning 警告
        with assert_warns(DeprecationWarning):
            # 调用 func 函数,传入指定的 axis 参数
            res = func(x, axis=axis)
            # 断言结果与 mask_rowcols 函数的返回值相等
            assert_equal(res, mask_rowcols(x, rowcols_axis))

    # 测试 dot 函数返回的结果是否为 MaskedArray 类型,参见 GitHub issue gh-6611
    def test_dot_returns_maskedarray(self):
        # 创建一个单位矩阵 a,并将其转换为 MaskedArray 类型的数组 b
        a = np.eye(3)
        b = array(a)
        # 断言 dot(a, a) 返回的类型是 MaskedArray
        assert_(type(dot(a, a)) is MaskedArray)
        # 断言 dot(a, b) 返回的类型是 MaskedArray
        assert_(type(dot(a, b)) is MaskedArray)
        # 断言 dot(b, a) 返回的类型是 MaskedArray
        assert_(type(dot(b, a)) is MaskedArray)
        # 断言 dot(b, b) 返回的类型是 MaskedArray
        assert_(type(dot(b, b)) is MaskedArray)

    # 测试 dot 函数的 out 参数功能
    def test_dot_out(self):
        # 创建一个单位矩阵 a,并将其转换为 MaskedArray 类型的数组
        a = array(np.eye(3))
        # 创建一个全零矩阵 out
        out = array(np.zeros((3, 3)))
        # 调用 dot 函数,将结果存储到预先创建的 out 矩阵中
        res = dot(a, a, out=out)
        # 断言返回的结果 res 是之前创建的 out 矩阵
        assert_(res is out)
        # 断言 a 和 res 的内容相等
        assert_equal(a, res)
class TestApplyAlongAxis:
    # Tests 2D functions
    def test_3d(self):
        # 创建一个 2x2x3 的三维数组
        a = arange(12.).reshape(2, 2, 3)

        # 定义一个操作函数,返回第二维度的数据
        def myfunc(b):
            return b[1]

        # 对数组 `a` 沿着第三个维度应用 myfunc 函数
        xa = apply_along_axis(myfunc, 2, a)
        # 断言结果与预期的相等
        assert_equal(xa, [[1, 4], [7, 10]])

    # Tests kwargs functions
    def test_3d_kwargs(self):
        # 创建一个 2x2x3 的三维数组
        a = arange(12).reshape(2, 2, 3)

        # 定义一个操作函数,带有一个偏移量参数,默认为 0
        def myfunc(b, offset=0):
            return b[1+offset]

        # 对数组 `a` 沿着第三个维度应用 myfunc 函数,并传入偏移量为 1
        xa = apply_along_axis(myfunc, 2, a, offset=1)
        # 断言结果与预期的相等
        assert_equal(xa, [[2, 5], [8, 11]])


class TestApplyOverAxes:
    # Tests apply_over_axes
    def test_basic(self):
        # 创建一个 2x3x4 的三维数组
        a = arange(24).reshape(2, 3, 4)
        
        # 在指定轴上应用 np.sum 函数,轴列表为 [0, 2]
        test = apply_over_axes(np.sum, a, [0, 2])
        # 创建控制数组,用于对比结果
        ctrl = np.array([[[60], [92], [124]]])
        # 断言结果与预期的相等
        assert_equal(test, ctrl)

        # 将数组中的奇数位置的元素设为 masked
        a[(a % 2).astype(bool)] = masked
        # 再次在指定轴上应用 np.sum 函数,轴列表为 [0, 2]
        test = apply_over_axes(np.sum, a, [0, 2])
        # 更新控制数组
        ctrl = np.array([[[28], [44], [60]]])
        # 断言结果与预期的相等
        assert_equal(test, ctrl)


class TestMedian:
    def test_pytype(self):
        # 计算包含无穷大的数组的中位数,沿着最后一个轴(-1)
        r = np.ma.median([[np.inf, np.inf], [np.inf, np.inf]], axis=-1)
        # 断言结果与预期的相等
        assert_equal(r, np.inf)

    def test_inf(self):
        # 测试处理含有 masked 的情况,计算包含无穷大的 masked 数组的中位数
        r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
                                             [np.inf, np.inf]]), axis=-1)
        # 断言结果与预期的相等
        assert_equal(r, np.inf)
        r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
                                             [np.inf, np.inf]]), axis=None)
        # 断言结果与预期的相等
        assert_equal(r, np.inf)
        # 所有元素都被 masked
        r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
                                             [np.inf, np.inf]], mask=True),
                         axis=-1)
        # 断言结果的 mask 全为 True
        assert_equal(r.mask, True)
        r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
                                             [np.inf, np.inf]], mask=True),
                         axis=None)
        # 断言结果的 mask 全为 True
        assert_equal(r.mask, True)

    def test_non_masked(self):
        # 测试处理未 masked 的情况
        x = np.arange(9)
        # 断言未 masked 情况下的中位数计算正确
        assert_equal(np.ma.median(x), 4.)
        # 断言返回的对象类型不是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        x = range(8)
        # 断言未 masked 情况下的中位数计算正确
        assert_equal(np.ma.median(x), 3.5)
        # 断言返回的对象类型不是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        x = 5
        # 断言未 masked 情况下的中位数计算正确
        assert_equal(np.ma.median(x), 5.)
        # 断言返回的对象类型不是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        # 整数类型的数组
        x = np.arange(9 * 8).reshape(9, 8)
        # 断言未 masked 情况下,沿着每列计算的中位数正确
        assert_equal(np.ma.median(x, axis=0), np.median(x, axis=0))
        # 断言未 masked 情况下,沿着每行计算的中位数正确
        assert_equal(np.ma.median(x, axis=1), np.median(x, axis=1))
        # 断言返回的对象类型不是 MaskedArray
        assert_(np.ma.median(x, axis=1) is not MaskedArray)
        # 浮点数类型的数组
        x = np.arange(9 * 8.).reshape(9, 8)
        # 断言未 masked 情况下,沿着每列计算的中位数正确
        assert_equal(np.ma.median(x, axis=0), np.median(x, axis=0))
        # 断言未 masked 情况下,沿着每行计算的中位数正确
        assert_equal(np.ma.median(x, axis=1), np.median(x, axis=1))
        # 断言返回的对象类型不是 MaskedArray
        assert_(np.ma.median(x, axis=1) is not MaskedArray)
    def test_docstring_examples(self):
        "test the examples given in the docstring of ma.median"
        # 创建一个长度为8的数组,其中前4个未屏蔽,后4个被屏蔽
        x = array(np.arange(8), mask=[0]*4 + [1]*4)
        # 断言计算数组的中位数为1.5
        assert_equal(np.ma.median(x), 1.5)
        # 断言中位数的形状为空元组
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言中位数不是 MaskedArray 类型
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个形状为(2, 5)的数组,其中前6个未屏蔽,后4个被屏蔽
        x = array(np.arange(10).reshape(2, 5), mask=[0]*6 + [1]*4)
        # 断言计算数组的中位数为2.5
        assert_equal(np.ma.median(x), 2.5)
        # 断言中位数的形状为空元组
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言中位数不是 MaskedArray 类型
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 在最后一个轴上计算中位数,覆盖输入数组
        ma_x = np.ma.median(x, axis=-1, overwrite_input=True)
        # 断言计算后的结果为[2., 5.]
        assert_equal(ma_x, [2., 5.])
        # 断言结果的形状为(2,)
        assert_equal(ma_x.shape, (2,), "shape mismatch")
        # 断言结果是 MaskedArray 类型
        assert_(type(ma_x) is MaskedArray)

    def test_axis_argument_errors(self):
        # 错误消息模板
        msg = "mask = %s, ndim = %s, axis = %s, overwrite_input = %s"
        # 遍历不同的数组维度
        for ndmin in range(5):
            # 遍历不同的掩码情况
            for mask in [False, True]:
                # 创建指定维度和掩码的数组
                x = array(1, ndmin=ndmin, mask=mask)

                # 对于每个轴和覆盖输入的组合,验证是否引发异常
                args = itertools.product(range(-ndmin, ndmin), [False, True])
                for axis, over in args:
                    try:
                        np.ma.median(x, axis=axis, overwrite_input=over)
                    except Exception:
                        raise AssertionError(msg % (mask, ndmin, axis, over))

                # 对于无效的轴值,验证是否引发 AxisError 异常
                args = itertools.product([-(ndmin + 1), ndmin], [False, True])
                for axis, over in args:
                    try:
                        np.ma.median(x, axis=axis, overwrite_input=over)
                    except np.exceptions.AxisError:
                        pass
                    else:
                        raise AssertionError(msg % (mask, ndmin, axis, over))

    def test_masked_0d(self):
        # 检查未屏蔽值的中位数
        x = array(1, mask=False)
        assert_equal(np.ma.median(x), 1)
        # 检查屏蔽值的中位数为 Masked
        x = array(1, mask=True)
        assert_equal(np.ma.median(x), np.ma.masked)
    def test_masked_1d(self):
        # 创建一个带掩码的一维数组 x
        x = array(np.arange(5), mask=True)
        # 断言计算 x 的中位数应该是掩码值
        assert_equal(np.ma.median(x), np.ma.masked)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型应该是 MaskedConstant
        assert_(type(np.ma.median(x)) is np.ma.core.MaskedConstant)
        
        # 创建一个没有掩码的一维数组 x
        x = array(np.arange(5), mask=False)
        # 断言计算 x 的中位数应该是 2.0
        assert_equal(np.ma.median(x), 2.)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个带有特定掩码的一维数组 x
        x = array(np.arange(5), mask=[0,1,0,0,0])
        # 断言计算 x 的中位数应该是 2.5
        assert_equal(np.ma.median(x), 2.5)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个完全被掩码的一维数组 x
        x = array(np.arange(5), mask=[0,1,1,1,1])
        # 断言计算 x 的中位数应该是 0.0
        assert_equal(np.ma.median(x), 0.)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个带有整数值的特定掩码的一维数组 x
        x = array(np.arange(5), mask=[0,1,1,0,0])
        # 断言计算 x 的中位数应该是 3.0
        assert_equal(np.ma.median(x), 3.)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个带有浮点数值的特定掩码的一维数组 x
        x = array(np.arange(5.), mask=[0,1,1,0,0])
        # 断言计算 x 的中位数应该是 3.0
        assert_equal(np.ma.median(x), 3.)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个带有整数值的复杂掩码的一维数组 x
        x = array(np.arange(6), mask=[0,1,1,1,1,0])
        # 断言计算 x 的中位数应该是 2.5
        assert_equal(np.ma.median(x), 2.5)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)
        
        # 创建一个带有浮点数值的复杂掩码的一维数组 x
        x = array(np.arange(6.), mask=[0,1,1,1,1,0])
        # 断言计算 x 的中位数应该是 2.5
        assert_equal(np.ma.median(x), 2.5)
        # 断言计算 x 的中位数的形状应该是标量
        assert_equal(np.ma.median(x).shape, (), "shape mismatch")
        # 断言 np.ma.median(x) 的类型不应该是 MaskedArray
        assert_(type(np.ma.median(x)) is not MaskedArray)

    def test_1d_shape_consistency(self):
        # 断言两个具有不同掩码的一维数组的中位数的形状应该相同
        assert_equal(np.ma.median(array([1,2,3],mask=[0,0,0])).shape,
                     np.ma.median(array([1,2,3],mask=[0,1,0])).shape )

    def test_2d(self):
        # 测试带有二维数组的中位数计算
        # 设置数组的行数和列数
        (n, p) = (101, 30)
        # 创建带掩码的一维数组 x
        x = masked_array(np.linspace(-1., 1., n),)
        # 在数组的开头和结尾添加掩码
        x[:10] = x[-10:] = masked
        # 创建一个空的二维数组 z
        z = masked_array(np.empty((n, p), dtype=float))
        # 将 x 复制到 z 的第一列
        z[:, 0] = x[:]
        # 创建一个索引数组
        idx = np.arange(len(x))
        # 随机打乱索引,并将打乱后的 x 复制到 z 的其余列中
        for i in range(1, p):
            np.random.shuffle(idx)
            z[:, i] = x[idx]
        # 断言 z 第一列的中位数应该是 0
        assert_equal(median(z[:, 0]), 0)
        # 断言 z 整体的中位数应该是 0
        assert_equal(median(z), 0)
        # 断言 z 每列的中位数应该是一个全为零的数组
        assert_equal(median(z, axis=0), np.zeros(p))
        # 断言 z 转置后每行的中位数应该是一个全为零的数组
        assert_equal(median(z.T, axis=1), np.zeros(p))
    def test_2d_waxis(self):
        # Tests median with 2D arrays and different axis.
        x = masked_array(np.arange(30).reshape(10, 3))
        x[:3] = x[-3:] = masked
        assert_equal(median(x), 14.5)
        assert_(type(np.ma.median(x)) is not MaskedArray)
        assert_equal(median(x, axis=0), [13.5, 14.5, 15.5])
        assert_(type(np.ma.median(x, axis=0)) is MaskedArray)
        assert_equal(median(x, axis=1), [0, 0, 0, 10, 13, 16, 19, 0, 0, 0])
        assert_(type(np.ma.median(x, axis=1)) is MaskedArray)
        assert_equal(median(x, axis=1).mask, [1, 1, 1, 0, 0, 0, 0, 1, 1, 1])

    def test_3d(self):
        # Tests median with 3D arrays.
        x = np.ma.arange(24).reshape(3, 4, 2)
        x[x % 3 == 0] = masked
        assert_equal(median(x, 0), [[12, 9], [6, 15], [12, 9], [18, 15]])
        x.shape = (4, 3, 2)
        assert_equal(median(x, 0), [[99, 10], [11, 99], [13, 14]])
        x = np.ma.arange(24).reshape(4, 3, 2)
        x[x % 5 == 0] = masked
        assert_equal(median(x, 0), [[12, 10], [8, 9], [16, 17]])

    def test_neg_axis(self):
        # Tests median with negative axis values.
        x = masked_array(np.arange(30).reshape(10, 3))
        x[:3] = x[-3:] = masked
        assert_equal(median(x, axis=-1), median(x, axis=1))

    def test_out_1d(self):
        # Tests median with output to 1D arrays.
        for v in (30, 30., 31, 31.):
            x = masked_array(np.arange(v))
            x[:3] = x[-3:] = masked
            out = masked_array(np.ones(()))
            r = median(x, out=out)
            if v == 30:
                assert_equal(out, 14.5)
            else:
                assert_equal(out, 15.)
            assert_(r is out)
            assert_(type(r) is MaskedArray)

    def test_out(self):
        # Tests median with output arrays.
        for v in (40, 40., 30, 30.):
            x = masked_array(np.arange(v).reshape(10, -1))
            x[:3] = x[-3:] = masked
            out = masked_array(np.ones(10))
            r = median(x, axis=1, out=out)
            if v == 30:
                e = masked_array([0.]*3 + [10, 13, 16, 19] + [0.]*3,
                                 mask=[True] * 3 + [False] * 4 + [True] * 3)
            else:
                e = masked_array([0.]*3 + [13.5, 17.5, 21.5, 25.5] + [0.]*3,
                                 mask=[True]*3 + [False]*4 + [True]*3)
            assert_equal(r, e)
            assert_(r is out)
            assert_(type(r) is MaskedArray)

    @pytest.mark.parametrize(
        argnames='axis',
        argvalues=[
            None,
            1,
            (1, ),
            (0, 1),
            (-3, -1),
        ]
    )
    def test_keepdims_out(self, axis):
        # 创建一个布尔类型的零矩阵作为遮罩,形状为 (3, 5, 7, 11)
        mask = np.zeros((3, 5, 7, 11), dtype=bool)
        # 随机设置部分元素为 True:
        w = np.random.random((4, 200)) * np.array(mask.shape)[:, None]
        w = w.astype(np.intp)
        # 将 mask 中指定位置设置为 NaN
        mask[tuple(w)] = np.nan
        # 使用 mask 创建一个带有遮罩的 masked_array 对象 d,初始值为全 1
        d = masked_array(np.ones(mask.shape), mask=mask)
        if axis is None:
            # 如果 axis 为 None,则输出形状为 d 的维度全为 1 的元组
            shape_out = (1,) * d.ndim
        else:
            # 根据传入的 axis 规范化后的元组
            axis_norm = normalize_axis_tuple(axis, d.ndim)
            # 根据 axis_norm 创建输出形状 shape_out
            shape_out = tuple(
                1 if i in axis_norm else d.shape[i] for i in range(d.ndim))
        # 创建一个空的 masked_array 对象 out,形状为 shape_out
        out = masked_array(np.empty(shape_out))
        # 计算 d 沿指定 axis 的中位数,保持维度为 True,并将结果存入 out
        result = median(d, axis=axis, keepdims=True, out=out)
        # 检查 result 是否为 out
        assert result is out
        # 检查 result 的形状是否与 shape_out 相同
        assert_equal(result.shape, shape_out)

    def test_single_non_masked_value_on_axis(self):
        # 创建一个包含非遮罩值的数据列表
        data = [[1., 0.],
                [0., 3.],
                [0., 0.]]
        # 创建一个带有遮罩值的 masked_array 对象 masked_arr
        masked_arr = np.ma.masked_equal(data, 0)
        # 预期的中位数值列表
        expected = [1., 3.]
        # 检查沿 axis=0 的中位数是否与预期值相等
        assert_array_equal(np.ma.median(masked_arr, axis=0),
                           expected)

    def test_nan(self):
        # 遍历两种 mask 情况
        for mask in (False, np.zeros(6, dtype=bool)):
            # 创建一个带有 NaN 值的 masked_array 对象 dm
            dm = np.ma.array([[1, np.nan, 3], [1, 2, 3]])
            dm.mask = mask

            # 标量结果
            r = np.ma.median(dm, axis=None)
            assert_(np.isscalar(r))
            assert_array_equal(r, np.nan)
            r = np.ma.median(dm.ravel(), axis=0)
            assert_(np.isscalar(r))
            assert_array_equal(r, np.nan)

            # 沿 axis=0 计算中位数,预期结果为 MaskedArray 类型
            r = np.ma.median(dm, axis=0)
            assert_equal(type(r), MaskedArray)
            assert_array_equal(r, [1, np.nan, 3])
            # 沿 axis=1 计算中位数,预期结果为 MaskedArray 类型
            r = np.ma.median(dm, axis=1)
            assert_equal(type(r), MaskedArray)
            assert_array_equal(r, [np.nan, 2])
            # 沿 axis=-1 计算中位数,预期结果为 MaskedArray 类型
            r = np.ma.median(dm, axis=-1)
            assert_equal(type(r), MaskedArray)
            assert_array_equal(r, [np.nan, 2])

        # 创建一个带有遮罩值的 masked_array 对象 dm
        dm = np.ma.array([[1, np.nan, 3], [1, 2, 3]])
        dm[:, 2] = np.ma.masked
        # 检查沿 axis=None 的中位数是否为 NaN
        assert_array_equal(np.ma.median(dm, axis=None), np.nan)
        # 沿 axis=0 计算中位数,预期结果为 [1, NaN, 3]
        assert_array_equal(np.ma.median(dm, axis=0), [1, np.nan, 3])
        # 沿 axis=1 计算中位数,预期结果为 [NaN, 1.5]
        assert_array_equal(np.ma.median(dm, axis=1), [np.nan, 1.5])

    def test_out_nan(self):
        # 创建一个全为零的 masked_array 对象 o
        o = np.ma.masked_array(np.zeros((4,)))
        # 创建一个全为一的 masked_array 对象 d,并设置部分值为 NaN 和遮罩
        d = np.ma.masked_array(np.ones((3, 4)))
        d[2, 1] = np.nan
        d[2, 2] = np.ma.masked
        # 沿 axis=0 计算中位数,并将结果存入 o,预期结果为 o 全为遮罩
        assert_equal(np.ma.median(d, 0, out=o), o)
        # 创建一个全为零的形状为 (3,) 的 masked_array 对象 o
        o = np.ma.masked_array(np.zeros((3,)))
        # 沿 axis=1 计算中位数,并将结果存入 o,预期结果为 o 全为遮罩
        assert_equal(np.ma.median(d, 1, out=o), o)
        # 创建一个全为零的标量 masked_array 对象 o
        o = np.ma.masked_array(np.zeros(()))
        # 计算整体中位数,并将结果存入 o,预期结果为 o 为遮罩
        assert_equal(np.ma.median(d, out=o), o)
    def test_nan_behavior(self):
        # 创建一个带有掩码数组的 MaskedArray 对象,包含从 0 到 23 的浮点数
        a = np.ma.masked_array(np.arange(24, dtype=float))
        # 设置每隔三个元素为掩码
        a[::3] = np.ma.masked
        # 将索引为 2 的元素设为 NaN
        a[2] = np.nan
        # 断言计算数组的中位数结果为 NaN
        assert_array_equal(np.ma.median(a), np.nan)
        # 断言沿着 axis=0 方向计算数组的中位数结果为 NaN
        assert_array_equal(np.ma.median(a, axis=0), np.nan)

        # 创建一个形状为 (2, 3, 4) 的带有掩码数组的 MaskedArray 对象
        a = np.ma.masked_array(np.arange(24, dtype=float).reshape(2, 3, 4))
        # 根据条件创建掩码
        a.mask = np.arange(a.size) % 2 == 1
        # 复制数组
        aorig = a.copy()
        # 将索引为 (1, 2, 3) 的元素设为 NaN
        a[1, 2, 3] = np.nan
        # 将索引为 (1, 1, 2) 的元素设为 NaN
        a[1, 1, 2] = np.nan

        # 没有指定 axis,断言计算数组的中位数结果为 NaN
        assert_array_equal(np.ma.median(a), np.nan)
        # 断言计算数组的中位数结果是标量
        assert_(np.isscalar(np.ma.median(a)))

        # 沿着 axis=0 方向计算数组的中位数,生成参考结果 b
        b = np.ma.median(aorig, axis=0)
        b[2, 3] = np.nan
        b[1, 2] = np.nan
        # 断言沿着 axis=0 方向计算数组的中位数与参考结果 b 相等
        assert_equal(np.ma.median(a, 0), b)

        # 沿着 axis=1 方向计算数组的中位数,生成参考结果 b
        b = np.ma.median(aorig, axis=1)
        b[1, 3] = np.nan
        b[1, 2] = np.nan
        # 断言沿着 axis=1 方向计算数组的中位数与参考结果 b 相等
        assert_equal(np.ma.median(a, 1), b)

        # 沿着 axis=(0, 2) 方向计算数组的中位数,生成参考结果 b
        b = np.ma.median(aorig, axis=(0, 2))
        b[1] = np.nan
        b[2] = np.nan
        # 断言沿着 axis=(0, 2) 方向计算数组的中位数与参考结果 b 相等
        assert_equal(np.ma.median(a, (0, 2)), b)

    def test_ambigous_fill(self):
        # 创建一个二维数组,使用 255 作为填充值
        # 255 被用作排序时的填充值
        a = np.array([[3, 3, 255], [3, 3, 255]], dtype=np.uint8)
        # 创建一个带有掩码的 MaskedArray 对象,将值为 3 的元素设为掩码
        a = np.ma.masked_array(a, mask=a == 3)
        # 断言沿着 axis=1 方向计算数组的中位数结果为 255
        assert_array_equal(np.ma.median(a, axis=1), 255)
        # 断言沿着 axis=1 方向计算数组的中位数的掩码为 False
        assert_array_equal(np.ma.median(a, axis=1).mask, False)
        # 断言沿着 axis=0 方向计算数组的中位数结果与 a 的第一行相等
        assert_array_equal(np.ma.median(a, axis=0), a[0])
        # 断言计算整个数组的中位数结果为 255
        assert_array_equal(np.ma.median(a), 255)
    # 定义一个名为 test_special 的测试方法,使用了 numpy 和 numpy.ma 模块
    def test_special(self):
        # 循环遍历列表中的 np.inf 和 -np.inf
        for inf in [np.inf, -np.inf]:
            # 创建一个包含 inf 和 np.nan 的二维数组 a
            a = np.array([[inf,  np.nan], [np.nan, np.nan]])
            # 使用 np.isnan(a) 创建一个布尔掩码,将其中的 NaN 设置为掩码
            a = np.ma.masked_array(a, mask=np.isnan(a))
            # 断言计算沿轴0和轴1的 a 的中位数,应为 [inf, np.nan]
            assert_equal(np.ma.median(a, axis=0), [inf,  np.nan])
            assert_equal(np.ma.median(a, axis=1), [inf,  np.nan])
            # 断言计算 a 的全局中位数,应为 inf
            assert_equal(np.ma.median(a), inf)

            # 创建另一个二维数组 a,包含 np.nan 和 inf
            a = np.array([[np.nan, np.nan, inf], [np.nan, np.nan, inf]])
            # 使用 np.isnan(a) 创建掩码,将其中的 NaN 设置为掩码
            a = np.ma.masked_array(a, mask=np.isnan(a))
            # 断言计算沿轴1的 a 的中位数,应为 inf
            assert_array_equal(np.ma.median(a, axis=1), inf)
            # 断言检查沿轴1的掩码,应为 False(即无掩码)
            assert_array_equal(np.ma.median(a, axis=1).mask, False)
            # 断言计算沿轴0的 a 的中位数,应为 a[0]
            assert_array_equal(np.ma.median(a, axis=0), a[0])
            # 断言计算 a 的全局中位数,应为 inf
            assert_array_equal(np.ma.median(a), inf)

            # 对于没有掩码的情况
            # 创建一个二维数组 a,包含 inf
            a = np.array([[inf, inf], [inf, inf]])
            # 断言计算 a 的全局中位数,应为 inf
            assert_equal(np.ma.median(a), inf)
            # 断言计算沿轴0的 a 的中位数,应为 inf
            assert_equal(np.ma.median(a, axis=0), inf)
            # 断言计算沿轴1的 a 的中位数,应为 inf
            assert_equal(np.ma.median(a, axis=1), inf)

            # 创建一个带有掩码的浮点数二维数组 a
            a = np.array([[inf, 7, -inf, -9],
                          [-10, np.nan, np.nan, 5],
                          [4, np.nan, np.nan, inf]],
                          dtype=np.float32)
            # 使用 np.isnan(a) 创建掩码,将其中的 NaN 设置为掩码
            a = np.ma.masked_array(a, mask=np.isnan(a))
            # 根据 inf 的正负值选择不同的断言条件
            if inf > 0:
                # 断言计算沿轴0的 a 的中位数,应为 [4., 7., -inf, 5.]
                assert_equal(np.ma.median(a, axis=0), [4., 7., -inf, 5.])
                # 断言计算 a 的全局中位数,应为 4.5
                assert_equal(np.ma.median(a), 4.5)
            else:
                # 断言计算沿轴0的 a 的中位数,应为 [-10., 7., -inf, -9.]
                assert_equal(np.ma.median(a, axis=0), [-10., 7., -inf, -9.])
                # 断言计算 a 的全局中位数,应为 -2.5
                assert_equal(np.ma.median(a), -2.5)
            # 断言计算沿轴1的 a 的中位数,应为 [-1., -2.5, inf]
            assert_equal(np.ma.median(a, axis=1), [-1., -2.5, inf])

            # 嵌套循环,生成多组具有不同数量 inf 的二维数组 a
            for i in range(0, 10):
                for j in range(1, 10):
                    # 创建一个二维数组 a,包含 i 个 np.nan 和 j 个 inf
                    a = np.array([([np.nan] * i) + ([inf] * j)] * 2)
                    # 使用 np.isnan(a) 创建掩码,将其中的 NaN 设置为掩码
                    a = np.ma.masked_array(a, mask=np.isnan(a))
                    # 断言计算 a 的全局中位数,应为 inf
                    assert_equal(np.ma.median(a), inf)
                    # 断言计算沿轴1的 a 的中位数,应为 inf
                    assert_equal(np.ma.median(a, axis=1), inf)
                    # 断言计算沿轴0的 a 的中位数,应为 ([np.nan] * i) + [inf] * j
                    assert_equal(np.ma.median(a, axis=0),
                                 ([np.nan] * i) + [inf] * j)
    # 定义测试方法,用于测试空数组情况
    def test_empty(self):
        # 创建一个空的掩码数组 a
        a = np.ma.masked_array(np.array([], dtype=float))
        # 在上下文中抑制特定警告
        with suppress_warnings() as w:
            # 记录 RuntimeWarning 警告
            w.record(RuntimeWarning)
            # 断言计算 a 的中位数结果为 NaN
            assert_array_equal(np.ma.median(a), np.nan)
            # 断言第一个记录的警告类别为 RuntimeWarning
            assert_(w.log[0].category is RuntimeWarning)

        # 创建一个多维空数组 a
        a = np.ma.masked_array(np.array([], dtype=float, ndmin=3))
        # 在上下文中抑制特定警告
        with suppress_warnings() as w:
            # 记录 RuntimeWarning 警告
            w.record(RuntimeWarning)
            # 设置警告过滤器,始终记录 RuntimeWarning
            warnings.filterwarnings('always', '', RuntimeWarning)
            # 断言计算 a 的中位数结果为 NaN
            assert_array_equal(np.ma.median(a), np.nan)
            # 断言第一个记录的警告类别为 RuntimeWarning
            assert_(w.log[0].category is RuntimeWarning)

        # 创建一个二维空数组 b
        b = np.ma.masked_array(np.array([], dtype=float, ndmin=2))
        # 断言沿轴 0 计算 a 的中位数结果与 b 相等
        assert_equal(np.ma.median(a, axis=0), b)
        # 断言沿轴 1 计算 a 的中位数结果与 b 相等
        assert_equal(np.ma.median(a, axis=1), b)

        # 创建一个二维包含 NaN 的数组 b
        b = np.ma.masked_array(np.array(np.nan, dtype=float, ndmin=2))
        # 在上下文中捕获警告
        with warnings.catch_warnings(record=True) as w:
            # 设置警告过滤器,始终记录 RuntimeWarning
            warnings.filterwarnings('always', '', RuntimeWarning)
            # 断言沿轴 2 计算 a 的中位数结果与 b 相等
            assert_equal(np.ma.median(a, axis=2), b)
            # 断言第一个记录的警告类别为 RuntimeWarning
            assert_(w[0].category is RuntimeWarning)

    # 定义测试方法,用于测试对象数组情况
    def test_object(self):
        # 创建一个对象数组 o,包含连续的数字
        o = np.ma.masked_array(np.arange(7.))
        # 断言 np.ma.median(o.astype(object)) 的类型为 float
        assert_(type(np.ma.median(o.astype(object))), float)
        # 将第二个元素设置为 NaN
        o[2] = np.nan
        # 断言 np.ma.median(o.astype(object)) 的类型为 float
        assert_(type(np.ma.median(o.astype(object))), float)
class TestCov:

    def setup_method(self):
        # 设置测试方法的初始化,创建一个包含随机数据的一维数组
        self.data = array(np.random.rand(12))

    def test_covhelper(self):
        x = self.data
        # 测试_covhelper函数的输出类型为float32
        assert_(_covhelper(x, rowvar=True)[1].dtype, np.float32)
        assert_(_covhelper(x, y=x, rowvar=False)[1].dtype, np.float32)
        # 测试在转换为float后,_covhelper函数的输出是否相等
        mask = x > 0.5
        assert_array_equal(
            _covhelper(
                np.ma.masked_array(x, mask), rowvar=True
            )[1].astype(bool),
            ~mask.reshape(1, -1),
        )
        assert_array_equal(
            _covhelper(
                np.ma.masked_array(x, mask), y=x, rowvar=False
            )[1].astype(bool),
            np.vstack((~mask, ~mask)),
        )

    def test_1d_without_missing(self):
        # 测试在没有缺失值的一维变量上计算协方差
        x = self.data
        assert_almost_equal(np.cov(x), cov(x))
        assert_almost_equal(np.cov(x, rowvar=False), cov(x, rowvar=False))
        assert_almost_equal(np.cov(x, rowvar=False, bias=True),
                            cov(x, rowvar=False, bias=True))

    def test_2d_without_missing(self):
        # 测试在没有缺失值的二维变量上计算协方差
        x = self.data.reshape(3, 4)
        assert_almost_equal(np.cov(x), cov(x))
        assert_almost_equal(np.cov(x, rowvar=False), cov(x, rowvar=False))
        assert_almost_equal(np.cov(x, rowvar=False, bias=True),
                            cov(x, rowvar=False, bias=True))

    def test_1d_with_missing(self):
        # 测试带有缺失值的一维变量上计算协方差
        x = self.data
        x[-1] = masked
        x -= x.mean()
        nx = x.compressed()
        assert_almost_equal(np.cov(nx), cov(x))
        assert_almost_equal(np.cov(nx, rowvar=False), cov(x, rowvar=False))
        assert_almost_equal(np.cov(nx, rowvar=False, bias=True),
                            cov(x, rowvar=False, bias=True))
        #
        try:
            # 测试在不允许使用遮罩的情况下调用cov函数是否会抛出ValueError异常
            cov(x, allow_masked=False)
        except ValueError:
            pass
        #
        # 测试带有缺失值的两个一维变量上计算协方差
        nx = x[1:-1]
        assert_almost_equal(np.cov(nx, nx[::-1]), cov(x, x[::-1]))
        assert_almost_equal(np.cov(nx, nx[::-1], rowvar=False),
                            cov(x, x[::-1], rowvar=False))
        assert_almost_equal(np.cov(nx, nx[::-1], rowvar=False, bias=True),
                            cov(x, x[::-1], rowvar=False, bias=True))
    # 定义一个测试方法,用于测试带有缺失值的二维变量的协方差函数
    def test_2d_with_missing(self):
        # 获取数据集并赋值给变量 x
        x = self.data
        # 将最后一个元素设置为缺失值 masked
        x[-1] = masked
        # 将 x 重新整形为 3 行 4 列的二维数组
        x = x.reshape(3, 4)
        # 生成一个逻辑非掩码数组,用于表示有效值
        valid = np.logical_not(getmaskarray(x)).astype(int)
        # 计算有效值矩阵的乘积,得到有效值的分数 frac
        frac = np.dot(valid, valid.T)
        # 对 x 减去每行均值并填充缺失值为 0,得到 xf
        xf = (x - x.mean(1)[:, None]).filled(0)
        # 使用自定义的协方差函数计算 xf 的协方差,并进行断言比较
        assert_almost_equal(cov(x),
                            np.cov(xf) * (x.shape[1] - 1) / (frac - 1.))
        # 使用带偏差的 np.cov 函数计算 xf 的协方差,并进行断言比较
        assert_almost_equal(cov(x, bias=True),
                            np.cov(xf, bias=True) * x.shape[1] / frac)
        # 重新计算有效值矩阵的乘积,得到有效值的分数 frac
        frac = np.dot(valid.T, valid)
        # 对 x 减去每列均值并填充缺失值为 0,得到 xf
        xf = (x - x.mean(0)).filled(0)
        # 使用自定义的协方差函数计算 xf 的协方差,并进行断言比较
        assert_almost_equal(cov(x, rowvar=False),
                            (np.cov(xf, rowvar=False) *
                             (x.shape[0] - 1) / (frac - 1.)))
        # 使用带偏差的 np.cov 函数计算 xf 的协方差,并进行断言比较
        assert_almost_equal(cov(x, rowvar=False, bias=True),
                            (np.cov(xf, rowvar=False, bias=True) *
                             x.shape[0] / frac))
class TestCorrcoef:

    def setup_method(self):
        # 设置测试方法的初始化,创建包含12个随机数的数组self.data和self.data2
        self.data = array(np.random.rand(12))
        self.data2 = array(np.random.rand(12))

    def test_ddof(self):
        # 测试ddof参数,预计会引发DeprecationWarning警告
        x, y = self.data, self.data2
        expected = np.corrcoef(x)
        expected2 = np.corrcoef(x, y)
        with suppress_warnings() as sup:
            warnings.simplefilter("always")
            assert_warns(DeprecationWarning, corrcoef, x, ddof=-1)
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            # ddof对函数几乎没有影响
            assert_almost_equal(np.corrcoef(x, ddof=0), corrcoef(x, ddof=0))
            assert_almost_equal(corrcoef(x, ddof=-1), expected)
            assert_almost_equal(corrcoef(x, y, ddof=-1), expected2)
            assert_almost_equal(corrcoef(x, ddof=3), expected)
            assert_almost_equal(corrcoef(x, y, ddof=3), expected2)

    def test_bias(self):
        x, y = self.data, self.data2
        expected = np.corrcoef(x)
        # 测试bias参数,预计会引发DeprecationWarning警告
        with suppress_warnings() as sup:
            warnings.simplefilter("always")
            assert_warns(DeprecationWarning, corrcoef, x, y, True, False)
            assert_warns(DeprecationWarning, corrcoef, x, y, True, True)
            assert_warns(DeprecationWarning, corrcoef, x, bias=False)
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            # bias对函数几乎没有影响
            assert_almost_equal(corrcoef(x, bias=1), expected)

    def test_1d_without_missing(self):
        # 测试没有缺失值的一维变量上的corrcoef函数
        x = self.data
        assert_almost_equal(np.corrcoef(x), corrcoef(x))
        assert_almost_equal(np.corrcoef(x, rowvar=False),
                            corrcoef(x, rowvar=False))
        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            assert_almost_equal(np.corrcoef(x, rowvar=False, bias=True),
                                corrcoef(x, rowvar=False, bias=True))

    def test_2d_without_missing(self):
        # 测试没有缺失值的二维变量上的corrcoef函数
        x = self.data.reshape(3, 4)
        assert_almost_equal(np.corrcoef(x), corrcoef(x))
        assert_almost_equal(np.corrcoef(x, rowvar=False),
                            corrcoef(x, rowvar=False))
        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            assert_almost_equal(np.corrcoef(x, rowvar=False, bias=True),
                                corrcoef(x, rowvar=False, bias=True))
    def test_1d_with_missing(self):
        # Test corrcoef 1 1D variable w/missing values
        # 使用带有缺失值的一维变量进行相关系数测试
        x = self.data
        x[-1] = masked
        # 将最后一个元素设为缺失值
        x -= x.mean()
        # 减去均值,标准化数据
        nx = x.compressed()
        # 去除缺失值后的数据
        assert_almost_equal(np.corrcoef(nx), corrcoef(x))
        # 检查相关系数函数对比,不考虑行变量
        assert_almost_equal(np.corrcoef(nx, rowvar=False),
                            corrcoef(x, rowvar=False))
        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            # 忽略特定警告,确保相关系数的偏置参数和自由度调整参数不影响结果
            assert_almost_equal(np.corrcoef(nx, rowvar=False, bias=True),
                                corrcoef(x, rowvar=False, bias=True))
        try:
            corrcoef(x, allow_masked=False)
        except ValueError:
            pass
        # 2个带有缺失值的一维变量
        nx = x[1:-1]
        assert_almost_equal(np.corrcoef(nx, nx[::-1]), corrcoef(x, x[::-1]))
        # 检查两个一维变量之间的相关系数,包括反向
        assert_almost_equal(np.corrcoef(nx, nx[::-1], rowvar=False),
                            corrcoef(x, x[::-1], rowvar=False))
        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            # ddof 和 bias 对函数几乎没有影响
            assert_almost_equal(np.corrcoef(nx, nx[::-1]),
                                corrcoef(x, x[::-1], bias=1))
            assert_almost_equal(np.corrcoef(nx, nx[::-1]),
                                corrcoef(x, x[::-1], ddof=2))

    def test_2d_with_missing(self):
        # Test corrcoef on 2D variable w/ missing value
        # 使用带有缺失值的二维变量进行相关系数测试
        x = self.data
        x[-1] = masked
        # 将最后一个元素设为缺失值
        x = x.reshape(3, 4)
        # 将数据重塑为3行4列的二维数组

        test = corrcoef(x)
        control = np.corrcoef(x)
        assert_almost_equal(test[:-1, :-1], control[:-1, :-1])
        # 检查二维数组的相关系数结果

        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            # ddof 和 bias 对函数几乎没有影响
            assert_almost_equal(corrcoef(x, ddof=-2)[:-1, :-1],
                                control[:-1, :-1])
            assert_almost_equal(corrcoef(x, ddof=3)[:-1, :-1],
                                control[:-1, :-1])
            assert_almost_equal(corrcoef(x, bias=1)[:-1, :-1],
                                control[:-1, :-1])
class TestPolynomial:
    # 多项式测试类

    def test_polyfit(self):
        # 测试 polyfit 函数
        # 对于 ndarrays
        x = np.random.rand(10)
        y = np.random.rand(20).reshape(-1, 2)
        assert_almost_equal(polyfit(x, y, 3), np.polyfit(x, y, 3))
        
        # 对于 1D maskedarrays
        x = x.view(MaskedArray)
        x[0] = masked
        y = y.view(MaskedArray)
        y[0, 0] = y[-1, -1] = masked
        
        # 测试 polyfit 函数的返回值,并进行断言比较
        (C, R, K, S, D) = polyfit(x, y[:, 0], 3, full=True)
        (c, r, k, s, d) = np.polyfit(x[1:], y[1:, 0].compressed(), 3,
                                     full=True)
        for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)):
            assert_almost_equal(a, a_)
        
        # 同样的测试方式,但是针对另一个列
        (C, R, K, S, D) = polyfit(x, y[:, -1], 3, full=True)
        (c, r, k, s, d) = np.polyfit(x[1:-1], y[1:-1, -1], 3, full=True)
        for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)):
            assert_almost_equal(a, a_)
        
        # 测试对整个 y 数组进行 polyfit 的情况
        (C, R, K, S, D) = polyfit(x, y, 3, full=True)
        (c, r, k, s, d) = np.polyfit(x[1:-1], y[1:-1,:], 3, full=True)
        for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)):
            assert_almost_equal(a, a_)
        
        # 测试带权重 w 的 polyfit
        w = np.random.rand(10) + 1
        wo = w.copy()
        xs = x[1:-1]
        ys = y[1:-1]
        ws = w[1:-1]
        (C, R, K, S, D) = polyfit(x, y, 3, full=True, w=w)
        (c, r, k, s, d) = np.polyfit(xs, ys, 3, full=True, w=ws)
        assert_equal(w, wo)
        for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)):
            assert_almost_equal(a, a_)

    def test_polyfit_with_masked_NaNs(self):
        # 测试带有 NaN 和 masked 值的 polyfit
        x = np.random.rand(10)
        y = np.random.rand(20).reshape(-1, 2)

        x[0] = np.nan
        y[-1,-1] = np.nan
        x = x.view(MaskedArray)
        y = y.view(MaskedArray)
        x[0] = masked
        y[-1,-1] = masked

        (C, R, K, S, D) = polyfit(x, y, 3, full=True)
        (c, r, k, s, d) = np.polyfit(x[1:-1], y[1:-1,:], 3, full=True)
        for (a, a_) in zip((C, R, K, S, D), (c, r, k, s, d)):
            assert_almost_equal(a, a_)


class TestArraySetOps:

    def test_unique_onlist(self):
        # 测试在列表上的 unique 函数
        data = [1, 1, 1, 2, 2, 3]
        test = unique(data, return_index=True, return_inverse=True)
        assert_(isinstance(test[0], MaskedArray))
        assert_equal(test[0], masked_array([1, 2, 3], mask=[0, 0, 0]))
        assert_equal(test[1], [0, 3, 5])
        assert_equal(test[2], [0, 0, 0, 1, 1, 2])
    def test_unique_onmaskedarray(self):
        # 测试在具有掩码数据的情况下使用 unique 函数,使用 use_mask=True 参数
        data = masked_array([1, 1, 1, 2, 2, 3], mask=[0, 0, 1, 0, 1, 0])
        test = unique(data, return_index=True, return_inverse=True)
        assert_equal(test[0], masked_array([1, 2, 3, -1], mask=[0, 0, 0, 1]))
        assert_equal(test[1], [0, 3, 5, 2])
        assert_equal(test[2], [0, 0, 3, 1, 3, 2])
        #
        # 设置数据的填充值为 3
        data.fill_value = 3
        # 使用给定的掩码和填充值创建掩码数组
        data = masked_array(data=[1, 1, 1, 2, 2, 3],
                            mask=[0, 0, 1, 0, 1, 0], fill_value=3)
        test = unique(data, return_index=True, return_inverse=True)
        assert_equal(test[0], masked_array([1, 2, 3, -1], mask=[0, 0, 0, 1]))
        assert_equal(test[1], [0, 3, 5, 2])
        assert_equal(test[2], [0, 0, 3, 1, 3, 2])

    def test_unique_allmasked(self):
        # 测试全为掩码数据的情况
        data = masked_array([1, 1, 1], mask=True)
        test = unique(data, return_index=True, return_inverse=True)
        assert_equal(test[0], masked_array([1, ], mask=[True]))
        assert_equal(test[1], [0])
        assert_equal(test[2], [0, 0, 0])
        #
        # 测试掩码数据的情况
        data = masked
        test = unique(data, return_index=True, return_inverse=True)
        assert_equal(test[0], masked_array(masked))
        assert_equal(test[1], [0])
        assert_equal(test[2], [0])

    def test_ediff1d(self):
        # 测试 ediff1d 函数
        x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1])
        control = array([1, 1, 1, 4], mask=[1, 0, 0, 1])
        test = ediff1d(x)
        assert_equal(test, control)
        assert_equal(test.filled(0), control.filled(0))
        assert_equal(test.mask, control.mask)

    def test_ediff1d_tobegin(self):
        # 测试带有 to_begin 参数的 ediff1d 函数
        x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1])
        test = ediff1d(x, to_begin=masked)
        control = array([0, 1, 1, 1, 4], mask=[1, 1, 0, 0, 1])
        assert_equal(test, control)
        assert_equal(test.filled(0), control.filled(0))
        assert_equal(test.mask, control.mask)
        #
        test = ediff1d(x, to_begin=[1, 2, 3])
        control = array([1, 2, 3, 1, 1, 1, 4], mask=[0, 0, 0, 1, 0, 0, 1])
        assert_equal(test, control)
        assert_equal(test.filled(0), control.filled(0))
        assert_equal(test.mask, control.mask)

    def test_ediff1d_toend(self):
        # 测试带有 to_end 参数的 ediff1d 函数
        x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1])
        test = ediff1d(x, to_end=masked)
        control = array([1, 1, 1, 4, 0], mask=[1, 0, 0, 1, 1])
        assert_equal(test, control)
        assert_equal(test.filled(0), control.filled(0))
        assert_equal(test.mask, control.mask)
        #
        test = ediff1d(x, to_end=[1, 2, 3])
        control = array([1, 1, 1, 4, 1, 2, 3], mask=[1, 0, 0, 1, 0, 0, 0])
        assert_equal(test, control)
        assert_equal(test.filled(0), control.filled(0))
        assert_equal(test.mask, control.mask)
    def test_ediff1d_tobegin_toend(self):
        # Test ediff1d w/ to_begin and to_end
        x = masked_array(np.arange(5), mask=[1, 0, 0, 0, 1])
        # 调用 ediff1d 函数,设置 to_begin 和 to_end 参数,并对结果进行测试
        test = ediff1d(x, to_end=masked, to_begin=masked)
        control = array([0, 1, 1, 1, 4, 0], mask=[1, 1, 0, 0, 1, 1])
        # 断言测试结果与预期结果相等
        assert_equal(test, control)
        # 断言测试结果经过填充后与预期结果经过填充后相等
        assert_equal(test.filled(0), control.filled(0))
        # 断言测试结果的屏蔽(mask)与预期结果的屏蔽相等
        assert_equal(test.mask, control.mask)
        #
        test = ediff1d(x, to_end=[1, 2, 3], to_begin=masked)
        control = array([0, 1, 1, 1, 4, 1, 2, 3],
                        mask=[1, 1, 0, 0, 1, 0, 0, 0])
        # 断言测试结果与预期结果相等
        assert_equal(test, control)
        # 断言测试结果经过填充后与预期结果经过填充后相等
        assert_equal(test.filled(0), control.filled(0))
        # 断言测试结果的屏蔽(mask)与预期结果的屏蔽相等
        assert_equal(test.mask, control.mask)

    def test_ediff1d_ndarray(self):
        # Test ediff1d w/ a ndarray
        x = np.arange(5)
        # 调用 ediff1d 函数,对 ndarray 进行处理,并进行测试
        test = ediff1d(x)
        control = array([1, 1, 1, 1], mask=[0, 0, 0, 0])
        # 断言测试结果与预期结果相等
        assert_equal(test, control)
        # 断言测试结果是 MaskedArray 类型
        assert_(isinstance(test, MaskedArray))
        # 断言测试结果经过填充后与预期结果经过填充后相等
        assert_equal(test.filled(0), control.filled(0))
        # 断言测试结果的屏蔽(mask)与预期结果的屏蔽相等
        assert_equal(test.mask, control.mask)
        #
        test = ediff1d(x, to_end=masked, to_begin=masked)
        control = array([0, 1, 1, 1, 1, 0], mask=[1, 0, 0, 0, 0, 1])
        # 断言测试结果是 MaskedArray 类型
        assert_(isinstance(test, MaskedArray))
        # 断言测试结果经过填充后与预期结果经过填充后相等
        assert_equal(test.filled(0), control.filled(0))
        # 断言测试结果的屏蔽(mask)与预期结果的屏蔽相等
        assert_equal(test.mask, control.mask)

    def test_intersect1d(self):
        # Test intersect1d
        x = array([1, 3, 3, 3], mask=[0, 0, 0, 1])
        y = array([3, 1, 1, 1], mask=[0, 0, 0, 1])
        # 调用 intersect1d 函数,测试两个数组的交集
        test = intersect1d(x, y)
        control = array([1, 3, -1], mask=[0, 0, 1])
        # 断言测试结果与预期结果相等
        assert_equal(test, control)

    def test_setxor1d(self):
        # Test setxor1d
        a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
        b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
        # 调用 setxor1d 函数,测试两个数组的对称差集
        test = setxor1d(a, b)
        assert_equal(test, array([3, 4, 7]))
        #
        a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
        b = [1, 2, 3, 4, 5]
        # 调用 setxor1d 函数,测试数组和普通序列的对称差集
        test = setxor1d(a, b)
        assert_equal(test, array([3, 4, 7, -1], mask=[0, 0, 0, 1]))
        #
        a = array([1, 2, 3])
        b = array([6, 5, 4])
        # 调用 setxor1d 函数,测试两个普通数组的对称差集
        test = setxor1d(a, b)
        assert_(isinstance(test, MaskedArray))
        assert_equal(test, [1, 2, 3, 4, 5, 6])
        #
        a = array([1, 8, 2, 3], mask=[0, 1, 0, 0])
        b = array([6, 5, 4, 8], mask=[0, 0, 0, 1])
        # 调用 setxor1d 函数,测试带屏蔽的数组的对称差集
        test = setxor1d(a, b)
        assert_(isinstance(test, MaskedArray))
        assert_equal(test, [1, 2, 3, 4, 5, 6])
        #
        # 断言空数组的对称差集为空
        assert_array_equal([], setxor1d([], []))
    def test_setxor1d_unique(self):
        # 测试 setxor1d 函数,使用 assume_unique=True 参数
        a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
        b = [1, 2, 3, 4, 5]
        # 调用 setxor1d 函数进行计算
        test = setxor1d(a, b, assume_unique=True)
        # 断言结果是否与预期相等
        assert_equal(test, array([3, 4, 7, -1], mask=[0, 0, 0, 1]))
        #
        a = array([1, 8, 2, 3], mask=[0, 1, 0, 0])
        b = array([6, 5, 4, 8], mask=[0, 0, 0, 1])
        # 再次调用 setxor1d 函数进行计算
        test = setxor1d(a, b, assume_unique=True)
        # 断言结果是否为 MaskedArray 类型
        assert_(isinstance(test, MaskedArray))
        # 断言结果是否与预期相等
        assert_equal(test, [1, 2, 3, 4, 5, 6])
        #
        a = array([[1], [8], [2], [3]])
        b = array([[6, 5], [4, 8]])
        # 第三次调用 setxor1d 函数进行计算
        test = setxor1d(a, b, assume_unique=True)
        # 断言结果是否为 MaskedArray 类型
        assert_(isinstance(test, MaskedArray))
        # 断言结果是否与预期相等
        assert_equal(test, [1, 2, 3, 4, 5, 6])

    def test_isin(self):
        # 大部分 isin 的行为已经由 in1d 的测试覆盖
        # 如果移除 in1d 函数,需要修改这些测试来测试 isin 函数。
        a = np.arange(24).reshape([2, 3, 4])
        mask = np.zeros([2, 3, 4])
        mask[1, 2, 0] = 1
        a = array(a, mask=mask)
        b = array(data=[0, 10, 20, 30,  1,  3, 11, 22, 33],
                  mask=[0,  1,  0,  1,  0,  1,  0,  1,  0])
        ec = zeros((2, 3, 4), dtype=bool)
        ec[0, 0, 0] = True
        ec[0, 0, 1] = True
        ec[0, 2, 3] = True
        # 调用 isin 函数进行计算
        c = isin(a, b)
        # 断言结果是否为 MaskedArray 类型
        assert_(isinstance(c, MaskedArray))
        # 断言结果数组是否与预期数组 ec 相等
        assert_array_equal(c, ec)
        # 将 np.isin 的结果与 ma.isin 进行比较
        d = np.isin(a, b[~b.mask]) & ~a.mask
        # 断言两者结果是否相等
        assert_array_equal(c, d)

    def test_in1d(self):
        # 测试 in1d 函数
        a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
        b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
        # 调用 in1d 函数进行计算
        test = in1d(a, b)
        # 断言结果是否与预期相等
        assert_equal(test, [True, True, True, False, True])
        #
        a = array([5, 5, 2, 1, -1], mask=[0, 0, 0, 0, 1])
        b = array([1, 5, -1], mask=[0, 0, 1])
        # 再次调用 in1d 函数进行计算
        test = in1d(a, b)
        # 断言结果是否与预期相等
        assert_equal(test, [True, True, False, True, True])
        #
        assert_array_equal([], in1d([], []))

    def test_in1d_invert(self):
        # 测试 in1d 函数的 invert 参数
        a = array([1, 2, 5, 7, -1], mask=[0, 0, 0, 0, 1])
        b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
        # 断言 np.invert(in1d(a, b)) 的结果与 in1d(a, b, invert=True) 的结果是否相等
        assert_equal(np.invert(in1d(a, b)), in1d(a, b, invert=True))

        a = array([5, 5, 2, 1, -1], mask=[0, 0, 0, 0, 1])
        b = array([1, 5, -1], mask=[0, 0, 1])
        # 断言 np.invert(in1d(a, b)) 的结果与 in1d(a, b, invert=True) 的结果是否相等
        assert_equal(np.invert(in1d(a, b)), in1d(a, b, invert=True))

        assert_array_equal([], in1d([], [], invert=True))
    # 定义测试函数test_union1d
    def test_union1d(self):
        # 测试union1d函数
        # 创建数组a,包含数据和掩码
        a = array([1, 2, 5, 7, 5, -1], mask=[0, 0, 0, 0, 0, 1])
        # 创建数组b,包含数据和掩码
        b = array([1, 2, 3, 4, 5, -1], mask=[0, 0, 0, 0, 0, 1])
        # 使用union1d函数对数组a和b进行合并
        test = union1d(a, b)
        # 创建参照数组control
        control = array([1, 2, 3, 4, 5, 7, -1], mask=[0, 0, 0, 0, 0, 0, 1])
        # 断言test和control是否相等
        assert_equal(test, control)

        # 测试gh-10340,union1d的参数如果不是1D,则应将其展开
        # 创建数组x,包含数据和掩码
        x = array([[0, 1, 2], [3, 4, 5]], mask=[[0, 0, 0], [0, 0, 1]])
        # 创建数组y,包含数据和掩码
        y = array([0, 1, 2, 3, 4], mask=[0, 0, 0, 0, 1])
        # 创建参照数组ez
        ez = array([0, 1, 2, 3, 4, 5], mask=[0, 0, 0, 0, 0, 1])
        # 使用union1d函数对数组x和y进行合并
        z = union1d(x, y)
        # 断言z和ez是否相等
        assert_equal(z, ez)
        # 断言空数组的情况
        assert_array_equal([], union1d([], []))

    # 定义测试函数test_setdiff1d
    def test_setdiff1d(self):
        # 测试setdiff1d函数
        # 创建数组a,包含数据和掩码
        a = array([6, 5, 4, 7, 7, 1, 2, 1], mask=[0, 0, 0, 0, 0, 0, 0, 1])
        # 创建数组b
        b = array([2, 4, 3, 3, 2, 1, 5])
        # 使用setdiff1d函数对数组a和b进行差集运算
        test = setdiff1d(a, b)
        # 断言test和期望的数组是否相等
        assert_equal(test, array([6, 7, -1], mask=[0, 0, 1]))
        # 测试arange的情况
        a = arange(10)
        b = arange(8)
        # 断言两个数组的差集是否与期望数组相等
        assert_equal(setdiff1d(a, b), array([8, 9]))
        a = array([], np.uint32, mask=[])
        # 断言setdiff1d返回的数据类型是否为uint32
        assert_equal(setdiff1d(a, []).dtype, np.uint32)

    # 定义测试函数test_setdiff1d_char_array
    def test_setdiff1d_char_array(self):
        # 测试setdiff1d_char_array函数
        # 创建包含字符的数组a和b
        a = np.array(['a', 'b', 'c'])
        b = np.array(['a', 'b', 's'])
        # 断言两个数组的差集是否与期望数组相等
        assert_array_equal(setdiff1d(a, b), np.array(['c']))
class TestShapeBase:

    def test_atleast_2d(self):
        # Test atleast_2d
        # 创建一个带有掩码的数组 `a`
        a = masked_array([0, 1, 2], mask=[0, 1, 0])
        # 对 `a` 运行 atleast_2d 函数,返回 `b`
        b = atleast_2d(a)
        # 断言 `b` 的形状为 (1, 3)
        assert_equal(b.shape, (1, 3))
        # 断言 `b` 的掩码形状与数据形状相同
        assert_equal(b.mask.shape, b.data.shape)
        # 断言 `a` 的形状为 (3,)
        assert_equal(a.shape, (3,))
        # 断言 `a` 的掩码形状与数据形状相同
        assert_equal(a.mask.shape, a.data.shape)
        # 再次断言 `b` 的掩码形状与数据形状相同
        assert_equal(b.mask.shape, b.data.shape)

    def test_shape_scalar(self):
        # the atleast and diagflat function should work with scalars
        # GitHub issue #3367
        # Additionally, the atleast functions should accept multiple scalars
        # correctly

        # 对标量值 1.0 运行 atleast_1d 函数,返回 `b`
        b = atleast_1d(1.0)
        # 断言 `b` 的形状为 (1,)
        assert_equal(b.shape, (1,))
        # 断言 `b` 的掩码形状与形状相同
        assert_equal(b.mask.shape, b.shape)
        # 断言 `b` 的数据形状与形状相同
        assert_equal(b.data.shape, b.shape)

        # 对多个标量值 1.0, 2.0 运行 atleast_1d 函数,返回 `b`
        b = atleast_1d(1.0, 2.0)
        # 对于 `b` 中的每个元素 `a`
        for a in b:
            # 断言 `a` 的形状为 (1,)
            assert_equal(a.shape, (1,))
            # 断言 `a` 的掩码形状与形状相同
            assert_equal(a.mask.shape, a.shape)
            # 断言 `a` 的数据形状与形状相同
            assert_equal(a.data.shape, a.shape)

        # 对标量值 1.0 运行 atleast_2d 函数,返回 `b`
        b = atleast_2d(1.0)
        # 断言 `b` 的形状为 (1, 1)
        assert_equal(b.shape, (1, 1))
        # 断言 `b` 的掩码形状与形状相同
        assert_equal(b.mask.shape, b.shape)
        # 断言 `b` 的数据形状与形状相同
        assert_equal(b.data.shape, b.shape)

        # 对多个标量值 1.0, 2.0 运行 atleast_2d 函数,返回 `b`
        b = atleast_2d(1.0, 2.0)
        # 对于 `b` 中的每个元素 `a`
        for a in b:
            # 断言 `a` 的形状为 (1, 1)
            assert_equal(a.shape, (1, 1))
            # 断言 `a` 的掩码形状与形状相同
            assert_equal(a.mask.shape, a.shape)
            # 断言 `a` 的数据形状与形状相同
            assert_equal(a.data.shape, a.shape)

        # 对标量值 1.0 运行 atleast_3d 函数,返回 `b`
        b = atleast_3d(1.0)
        # 断言 `b` 的形状为 (1, 1, 1)
        assert_equal(b.shape, (1, 1, 1))
        # 断言 `b` 的掩码形状与形状相同
        assert_equal(b.mask.shape, b.shape)
        # 断言 `b` 的数据形状与形状相同
        assert_equal(b.data.shape, b.shape)

        # 对多个标量值 1.0, 2.0 运行 atleast_3d 函数,返回 `b`
        b = atleast_3d(1.0, 2.0)
        # 对于 `b` 中的每个元素 `a`
        for a in b:
            # 断言 `a` 的形状为 (1, 1, 1)
            assert_equal(a.shape, (1, 1, 1))
            # 断言 `a` 的掩码形状与形状相同
            assert_equal(a.mask.shape, a.shape)
            # 断言 `a` 的数据形状与形状相同
            assert_equal(a.data.shape, a.shape)

        # 对标量值 1.0 运行 diagflat 函数,返回 `b`
        b = diagflat(1.0)
        # 断言 `b` 的形状为 (1, 1)
        assert_equal(b.shape, (1, 1))
        # 断言 `b` 的掩码形状与数据形状相同
        assert_equal(b.mask.shape, b.data.shape)


class TestNDEnumerate:

    def test_ndenumerate_nomasked(self):
        # 创建普通数组 `ordinary`
        ordinary = np.arange(6.).reshape((1, 3, 2))
        # 创建与 `ordinary` 相同形状的全零掩码数组 `empty_mask`
        empty_mask = np.zeros_like(ordinary, dtype=bool)
        # 使用 `empty_mask` 创建带有掩码的数组 `with_mask`
        with_mask = masked_array(ordinary, mask=empty_mask)
        # 断言 `np.ndenumerate(ordinary)` 与 `ndenumerate(ordinary)` 的结果列表相同
        assert_equal(list(np.ndenumerate(ordinary)),
                     list(ndenumerate(ordinary)))
        # 断言 `ndenumerate(ordinary)` 与 `ndenumerate(with_mask)` 的结果列表相同
        assert_equal(list(ndenumerate(ordinary)),
                     list(ndenumerate(with_mask)))
        # 断言 `ndenumerate(with_mask)` 与 `ndenumerate(with_mask, compressed=False)` 的结果列表相同
        assert_equal(list(ndenumerate(with_mask)),
                     list(ndenumerate(with_mask, compressed=False)))

    def test_ndenumerate_allmasked(self):
        # 创建全掩码数组 `a`
        a = masked_all(())
        # 创建形状为 (100,) 的全掩码数组 `b`
        b = masked_all((100,))
        # 创建形状为 (2, 3, 4) 的全掩码数组 `c`
        c = masked_all((2, 3, 4))
        # 断言 `ndenumerate(a)` 的结果列表为空
        assert_equal(list(ndenumerate(a)), [])
        # 断言 `ndenumerate(b)` 的结果列表为空
        assert_equal(list(ndenumerate(b)), [])
        # 断言 `ndenumerate(b, compressed=False)` 的结果列表与预期列表相同
        assert_equal(list(ndenumerate(b, compressed=False)),
                     list(zip(np.ndindex((100,)), 100 * [masked])))
        # 断言 `ndenumerate(c)` 的结果列表为空
        assert_equal(list(ndenumerate(c)), [])
        # 断言 `ndenumerate(c, compressed=False)` 的结果列表与预期列表相同
        assert_equal(list(ndenumerate(c, compressed=False)),
                     list(zip(np.ndindex((2, 3, 4)), 2 * 3 * 4 * [masked])))
    # 定义一个测试函数,用于测试混合掩码的ndenumerate功能
    def test_ndenumerate_mixedmasked(self):
        # 创建一个包含掩码的数组a,形状为(3, 4),范围从0到11
        a = masked_array(np.arange(12).reshape((3, 4)),
                         mask=[[1, 1, 1, 1],
                               [1, 1, 0, 1],
                               [0, 0, 0, 0]])
        # 预期的迭代结果,包含一系列((行索引, 列索引), 值)的元组
        items = [((1, 2), 6),
                 ((2, 0), 8), ((2, 1), 9), ((2, 2), 10), ((2, 3), 11)]
        # 断言ndenumerate函数返回的结果与预期的items相等
        assert_equal(list(ndenumerate(a)), items)
        # 断言使用compressed=False参数时,ndenumerate函数返回的元素个数等于数组a的大小
        assert_equal(len(list(ndenumerate(a, compressed=False))), a.size)
        # 遍历使用compressed=False参数的ndenumerate函数的结果
        for coordinate, value in ndenumerate(a, compressed=False):
            # 断言遍历的每个坐标对应的值与数组a中对应位置的值相等
            assert_equal(a[coordinate], value)
class TestStack:

    def test_stack_1d(self):
        # 创建两个带掩码的一维数组
        a = masked_array([0, 1, 2], mask=[0, 1, 0])
        b = masked_array([9, 8, 7], mask=[1, 0, 0])

        # 在 axis=0 上堆叠数组 a 和 b
        c = stack([a, b], axis=0)
        # 断言堆叠后的数组形状为 (2, 3)
        assert_equal(c.shape, (2, 3))
        # 断言 a 的掩码与堆叠后的第一个元素的掩码相同
        assert_array_equal(a.mask, c[0].mask)
        # 断言 b 的掩码与堆叠后的第二个元素的掩码相同

        assert_array_equal(b.mask, c[1].mask)

        # 在垂直方向堆叠数组 a 和 b
        d = vstack([a, b])
        # 断言堆叠后的数据部分相同
        assert_array_equal(c.data, d.data)
        # 断言堆叠后的掩码部分相同
        assert_array_equal(c.mask, d.mask)

        # 在 axis=1 上堆叠数组 a 和 b
        c = stack([a, b], axis=1)
        # 断言堆叠后的数组形状为 (3, 2)
        assert_equal(c.shape, (3, 2))
        # 断言 a 的掩码与堆叠后第一列的掩码相同
        assert_array_equal(a.mask, c[:, 0].mask)
        # 断言 b 的掩码与堆叠后第二列的掩码相同

        assert_array_equal(b.mask, c[:, 1].mask)

    def test_stack_masks(self):
        # 创建两个带掩码的一维数组,其中 a 的所有元素都被掩码,b 没有掩码
        a = masked_array([0, 1, 2], mask=True)
        b = masked_array([9, 8, 7], mask=False)

        # 在 axis=0 上堆叠数组 a 和 b
        c = stack([a, b], axis=0)
        # 断言堆叠后的数组形状为 (2, 3)
        assert_equal(c.shape, (2, 3))
        # 断言 a 的掩码与堆叠后的第一个元素的掩码相同
        assert_array_equal(a.mask, c[0].mask)
        # 断言 b 的掩码与堆叠后的第二个元素的掩码相同

        assert_array_equal(b.mask, c[1].mask)

        # 在垂直方向堆叠数组 a 和 b
        d = vstack([a, b])
        # 断言堆叠后的数据部分相同
        assert_array_equal(c.data, d.data)
        # 断言堆叠后的掩码部分相同
        assert_array_equal(c.mask, d.mask)

        # 在 axis=1 上堆叠数组 a 和 b
        c = stack([a, b], axis=1)
        # 断言堆叠后的数组形状为 (3, 2)
        assert_equal(c.shape, (3, 2))
        # 断言 a 的掩码与堆叠后第一列的掩码相同
        assert_array_equal(a.mask, c[:, 0].mask)
        # 断言 b 的掩码与堆叠后第二列的掩码相同

        assert_array_equal(b.mask, c[:, 1].mask)

    def test_stack_nd(self):
        # 创建两个多维数组 a1 和 a2,每个元素都带有随机掩码
        shp = (3, 2)
        d1 = np.random.randint(0, 10, shp)
        d2 = np.random.randint(0, 10, shp)
        m1 = np.random.randint(0, 2, shp).astype(bool)
        m2 = np.random.randint(0, 2, shp).astype(bool)
        a1 = masked_array(d1, mask=m1)
        a2 = masked_array(d2, mask=m2)

        # 在 axis=0 上堆叠数组 a1 和 a2
        c = stack([a1, a2], axis=0)
        c_shp = (2,) + shp
        # 断言堆叠后的数组形状符合预期
        assert_equal(c.shape, c_shp)
        # 断言 a1 的掩码与堆叠后的第一个元素的掩码相同
        assert_array_equal(a1.mask, c[0].mask)
        # 断言 a2 的掩码与堆叠后的第二个元素的掩码相同

        assert_array_equal(a2.mask, c[1].mask)

        # 在 axis=-1 上堆叠数组 a1 和 a2
        c = stack([a1, a2], axis=-1)
        c_shp = shp + (2,)
        # 断言堆叠后的数组形状符合预期
        assert_equal(c.shape, c_shp)
        # 断言 a1 的掩码与堆叠后的第一个元素的掩码相同
        assert_array_equal(a1.mask, c[..., 0].mask)
        # 断言 a2 的掩码与堆叠后的第二个元素的掩码相同

        assert_array_equal(a2.mask, c[..., 1].mask)

        # 创建两个四维数组 a1 和 a2,每个元素都带有随机掩码
        shp = (3, 2, 4, 5,)
        d1 = np.random.randint(0, 10, shp)
        d2 = np.random.randint(0, 10, shp)
        m1 = np.random.randint(0, 2, shp).astype(bool)
        m2 = np.random.randint(0, 2, shp).astype(bool)
        a1 = masked_array(d1, mask=m1)
        a2 = masked_array(d2, mask=m2)

        # 在 axis=0 上堆叠数组 a1 和 a2
        c = stack([a1, a2], axis=0)
        c_shp = (2,) + shp
        # 断言堆叠后的数组形状符合预期
        assert_equal(c.shape, c_shp)
        # 断言 a1 的掩码与堆叠后的第一个元素的掩码相同
        assert_array_equal(a1.mask, c[0].mask)
        # 断言 a2 的掩码与堆叠后的第二个元素的掩码相同

        assert_array_equal(a2.mask, c[1].mask)

        # 在 axis=-1 上堆叠数组 a1 和 a2
        c = stack([a1, a2], axis=-1)
        c_shp = shp + (2,)
        # 断言堆叠后的数组形状符合预期
        assert_equal(c.shape, c_shp)
        # 断言 a1 的掩码与堆叠后的第一个元素的掩码相同
        assert_array_equal(a1.mask, c[..., 0].mask)
        # 断言 a2 的掩码与堆叠后的第二个元素的掩码相同

        assert_array_equal(a2.mask, c[..., 1].mask)

.\numpy\numpy\ma\tests\test_mrecords.py

# pylint: disable-msg=W0611, W0612, W0511,R0201
"""Tests suite for mrecords.

:author: Pierre Gerard-Marchant
:contact: pierregm_at_uga_dot_edu

"""
# 导入pickle模块,用于对象序列化和反序列化
import pickle

# 导入NumPy库及其模块
import numpy as np
import numpy.ma as ma

# 导入NumPy中的masked和nomask函数
from numpy.ma import masked, nomask

# 导入NumPy中的temppath函数,用于临时路径处理
from numpy.testing import temppath

# 导入NumPy中的recarray, recfromrecords, recfromarrays等记录相关函数
from numpy._core.records import (
    recarray, fromrecords as recfromrecords, fromarrays as recfromarrays
    )

# 导入NumPy中的MaskedRecords, mrecarray, fromarrays, fromtextfile, fromrecords, addfield等记录相关函数
from numpy.ma.mrecords import (
    MaskedRecords, mrecarray, fromarrays, fromtextfile, fromrecords, addfield
    )

# 导入NumPy测试工具函数
from numpy.ma.testutils import (
    assert_, assert_equal,
    assert_equal_records,
    )

# 定义测试类TestMRecords
class TestMRecords:

    # 初始化测试数据
    ilist = [1, 2, 3, 4, 5]
    flist = [1.1, 2.2, 3.3, 4.4, 5.5]
    slist = [b'one', b'two', b'three', b'four', b'five']
    ddtype = [('a', int), ('b', float), ('c', '|S8')]
    mask = [0, 1, 0, 0, 1]
    base = ma.array(list(zip(ilist, flist, slist)), mask=mask, dtype=ddtype)

    # 定义测试方法test_byview
    def test_byview(self):
        # Test creation by view
        base = self.base  # 获取测试数据
        mbase = base.view(mrecarray)  # 将base转换为mrecarray类型
        assert_equal(mbase.recordmask, base.recordmask)  # 断言recordmask相等
        assert_equal_records(mbase._mask, base._mask)  # 断言_mask属性相等
        assert_(isinstance(mbase._data, recarray))  # 断言_data属性是recarray类型
        assert_equal_records(mbase._data, base._data.view(recarray))  # 断言_data属性与base的data属性视图相等
        for field in ('a', 'b', 'c'):
            assert_equal(base[field], mbase[field])  # 断言字段a、b、c在base和mbase中的值相等
        assert_equal_records(mbase.view(mrecarray), mbase)  # 断言mbase视图为mrecarray后仍等于mbase本身
    # 定义一个测试方法 `test_get`
    def test_get(self):
        # 测试字段的检索
        base = self.base.copy()
        mbase = base.view(mrecarray)
        
        # 遍历字段 'a', 'b', 'c'
        for field in ('a', 'b', 'c'):
            # 断言获取属性与获取字段内容相等
            assert_equal(getattr(mbase, field), mbase[field])
            # 断言基本数据与视图数据中的字段内容相等
            assert_equal(base[field], mbase[field])
        
        # 获取第一个元素
        mbase_first = mbase[0]
        # 断言第一个元素是 `mrecarray` 类型
        assert_(isinstance(mbase_first, mrecarray))
        # 断言第一个元素的数据类型与整体数据类型相同
        assert_equal(mbase_first.dtype, mbase.dtype)
        # 断言第一个元素的转换为列表后内容正确
        assert_equal(mbase_first.tolist(), (1, 1.1, b'one'))
        # 断言第一个元素的记录掩码为 `nomask`
        assert_equal(mbase_first.recordmask, nomask)
        # 断言第一个元素的掩码为全 `False`
        assert_equal(mbase_first._mask.item(), (False, False, False))
        # 断言通过索引 'a' 获取的内容与 `mbase['a'][0]` 相等
        assert_equal(mbase_first['a'], mbase['a'][0])
        
        # 获取最后一个元素
        mbase_last = mbase[-1]
        # 断言最后一个元素是 `mrecarray` 类型
        assert_(isinstance(mbase_last, mrecarray))
        # 断言最后一个元素的数据类型与整体数据类型相同
        assert_equal(mbase_last.dtype, mbase.dtype)
        # 断言最后一个元素的转换为列表后内容正确
        assert_equal(mbase_last.tolist(), (None, None, None))
        # 断言最后一个元素的记录掩码为 `True`
        assert_equal(mbase_last.recordmask, True)
        # 断言最后一个元素的掩码为全 `True`
        assert_equal(mbase_last._mask.item(), (True, True, True))
        # 断言通过索引 'a' 获取的内容为 `masked`
        assert_((mbase_last['a'] is masked))
        
        # 获取切片
        mbase_sl = mbase[:2]
        # 断言切片是 `mrecarray` 类型
        assert_(isinstance(mbase_sl, mrecarray))
        # 断言切片的数据类型与整体数据类型相同
        assert_equal(mbase_sl.dtype, mbase.dtype)
        # 断言切片的记录掩码为 `[0, 1]`
        assert_equal(mbase_sl.recordmask, [0, 1])
        # 断言切片的掩码与给定的掩码数组相等
        assert_equal_records(mbase_sl.mask,
                             np.array([(False, False, False),
                                       (True, True, True)],
                                      dtype=mbase._mask.dtype))
        # 断言切片内容与基本数据的前两个元素视图相等
        assert_equal_records(mbase_sl, base[:2].view(mrecarray))
        
        # 再次遍历字段 'a', 'b', 'c'
        for field in ('a', 'b', 'c'):
            # 断言获取属性与获取基本数据前两个元素的字段内容相等
            assert_equal(getattr(mbase_sl, field), base[:2][field])
    def test_set_fields(self):
        # Tests setting fields.
        base = self.base.copy()  # 复制 self.base 到 base
        mbase = base.view(mrecarray)  # 将 base 转换为 mrecarray 视图,并赋给 mbase
        mbase = mbase.copy()  # 复制 mbase 自身,生成一个新的副本
        mbase.fill_value = (999999, 1e20, 'N/A')  # 设置 mbase 的填充值
        # Change the data, the mask should be conserved
        mbase.a._data[:] = 5  # 修改 mbase 中字段 'a' 的数据为 5
        assert_equal(mbase['a']._data, [5, 5, 5, 5, 5])  # 断言检查 'a' 字段的数据是否为 [5, 5, 5, 5, 5]
        assert_equal(mbase['a']._mask, [0, 1, 0, 0, 1])  # 断言检查 'a' 字段的掩码是否为 [0, 1, 0, 0, 1]
        # Change the elements, and the mask will follow
        mbase.a = 1  # 将 mbase 中字段 'a' 的所有元素设置为 1
        assert_equal(mbase['a']._data, [1]*5)  # 断言检查 'a' 字段的数据是否全部为 1
        assert_equal(ma.getmaskarray(mbase['a']), [0]*5)  # 断言检查 'a' 字段的掩码是否全部为 0
        # Use to be _mask, now it's recordmask
        assert_equal(mbase.recordmask, [False]*5)  # 断言检查 recordmask 是否全部为 False
        assert_equal(mbase._mask.tolist(),
                     np.array([(0, 0, 0),
                               (0, 1, 1),
                               (0, 0, 0),
                               (0, 0, 0),
                               (0, 1, 1)],
                              dtype=bool))  # 断言检查整体的掩码矩阵是否符合预期
        # Set a field to mask ........................
        mbase.c = masked  # 将 mbase 中字段 'c' 的所有元素设置为 masked(掩码状态)
        # Use to be mask, and now it's still mask !
        assert_equal(mbase.c.mask, [1]*5)  # 断言检查 'c' 字段的掩码是否全部为 1
        assert_equal(mbase.c.recordmask, [1]*5)  # 断言检查 'c' 字段的 recordmask 是否全部为 1
        assert_equal(ma.getmaskarray(mbase['c']), [1]*5)  # 断言检查 'c' 字段的掩码是否全部为 1
        assert_equal(ma.getdata(mbase['c']), [b'N/A']*5)  # 断言检查 'c' 字段的数据是否全部为 b'N/A'
        assert_equal(mbase._mask.tolist(),
                     np.array([(0, 0, 1),
                               (0, 1, 1),
                               (0, 0, 1),
                               (0, 0, 1),
                               (0, 1, 1)],
                              dtype=bool))  # 断言检查整体的掩码矩阵是否符合预期
        # Set fields by slices .......................
        mbase = base.view(mrecarray).copy()  # 将 base 转换为 mrecarray 视图,并复制一份给 mbase
        mbase.a[3:] = 5  # 将 mbase 中字段 'a' 的索引从 3 开始的元素设置为 5
        assert_equal(mbase.a, [1, 2, 3, 5, 5])  # 断言检查 'a' 字段的数据是否符合预期
        assert_equal(mbase.a._mask, [0, 1, 0, 0, 0])  # 断言检查 'a' 字段的掩码是否符合预期
        mbase.b[3:] = masked  # 将 mbase 中字段 'b' 的索引从 3 开始的元素设置为 masked(掩码状态)
        assert_equal(mbase.b, base['b'])  # 断言检查 'b' 字段的数据是否符合 base 中相应字段的预期
        assert_equal(mbase.b._mask, [0, 1, 0, 1, 1])  # 断言检查 'b' 字段的掩码是否符合预期
        # Set fields globally..........................
        ndtype = [('alpha', '|S1'), ('num', int)]  # 定义一个结构化数据类型
        data = ma.array([('a', 1), ('b', 2), ('c', 3)], dtype=ndtype)  # 创建一个结构化数组
        rdata = data.view(MaskedRecords)  # 将结构化数组转换为 MaskedRecords 视图
        val = ma.array([10, 20, 30], mask=[1, 0, 0])  # 创建一个带有掩码的数组

        rdata['num'] = val  # 将 rdata 中字段 'num' 的值设置为 val
        assert_equal(rdata.num, val)  # 断言检查 'num' 字段的数据是否符合预期
        assert_equal(rdata.num.mask, [1, 0, 0])  # 断言检查 'num' 字段的掩码是否符合预期

    def test_set_fields_mask(self):
        # Tests setting the mask of a field.
        base = self.base.copy()  # 复制 self.base 到 base
        # This one has already a mask....
        mbase = base.view(mrecarray)  # 将 base 转换为 mrecarray 视图,并赋给 mbase
        mbase['a'][-2] = masked  # 将 mbase 中字段 'a' 的倒数第二个元素设置为 masked(掩码状态)
        assert_equal(mbase.a, [1, 2, 3, 4, 5])  # 断言检查 'a' 字段的数据是否符合预期
        assert_equal(mbase.a._mask, [0, 1, 0, 1, 1])  # 断言检查 'a' 字段的掩码是否符合预期
        # This one has not yet
        mbase = fromarrays([np.arange(5), np.random.rand(5)],
                           dtype=[('a', int), ('b', float)])  # 创建一个新的 mrecarray
        mbase['a'][-2] = masked  # 将 mbase 中字段 'a' 的倒数第二个元素设置为 masked(掩码状态)
        assert_equal(mbase.a, [0, 1, 2, 3, 4])  # 断言检查 'a' 字段的数据是否符合预期
        assert_equal(mbase.a._mask, [0, 0, 0, 1, 0])  # 断言检查 'a' 字段的掩码是否符合预期
    def test_set_mask(self):
        base = self.base.copy()
        mbase = base.view(mrecarray)
        # 设置掩码为True
        mbase.mask = masked
        # 断言:确保mbase['b']的掩码为全1数组
        assert_equal(ma.getmaskarray(mbase['b']), [1]*5)
        # 断言:确保mbase['a']和mbase['b']的掩码相同
        assert_equal(mbase['a']._mask, mbase['b']._mask)
        # 断言:确保mbase['a']和mbase['c']的掩码相同
        assert_equal(mbase['a']._mask, mbase['c']._mask)
        # 断言:确保mbase整体的掩码为全1数组
        assert_equal(mbase._mask.tolist(),
                     np.array([(1, 1, 1)]*5, dtype=bool))
        # 删除掩码
        mbase.mask = nomask
        # 断言:确保mbase['c']的掩码为全0数组
        assert_equal(ma.getmaskarray(mbase['c']), [0]*5)
        # 断言:确保mbase整体的掩码为全0数组
        assert_equal(mbase._mask.tolist(),
                     np.array([(0, 0, 0)]*5, dtype=bool))

    def test_set_mask_fromarray(self):
        base = self.base.copy()
        mbase = base.view(mrecarray)
        # 使用数组设置掩码
        mbase.mask = [1, 0, 0, 0, 1]
        # 断言:确保mbase.a的掩码为指定数组
        assert_equal(mbase.a.mask, [1, 0, 0, 0, 1])
        # 断言:确保mbase.b的掩码为指定数组
        assert_equal(mbase.b.mask, [1, 0, 0, 0, 1])
        # 断言:确保mbase.c的掩码为指定数组
        assert_equal(mbase.c.mask, [1, 0, 0, 0, 1])
        # 再次设置掩码
        mbase.mask = [0, 0, 0, 0, 1]
        # 断言:确保mbase.a的掩码为指定数组
        assert_equal(mbase.a.mask, [0, 0, 0, 0, 1])
        # 断言:确保mbase.b的掩码为指定数组
        assert_equal(mbase.b.mask, [0, 0, 0, 0, 1])
        # 断言:确保mbase.c的掩码为指定数组
        assert_equal(mbase.c.mask, [0, 0, 0, 0, 1])

    def test_set_mask_fromfields(self):
        mbase = self.base.copy().view(mrecarray)

        nmask = np.array(
            [(0, 1, 0), (0, 1, 0), (1, 0, 1), (1, 0, 1), (0, 0, 0)],
            dtype=[('a', bool), ('b', bool), ('c', bool)])
        # 使用字段数组设置掩码
        mbase.mask = nmask
        # 断言:确保mbase.a的掩码为指定数组
        assert_equal(mbase.a.mask, [0, 0, 1, 1, 0])
        # 断言:确保mbase.b的掩码为指定数组
        assert_equal(mbase.b.mask, [1, 1, 0, 0, 0])
        # 断言:确保mbase.c的掩码为指定数组
        assert_equal(mbase.c.mask, [0, 0, 1, 1, 0])
        # 重新初始化并再次设置掩码
        mbase.mask = False
        mbase.fieldmask = nmask
        # 断言:确保mbase.a的掩码为指定数组
        assert_equal(mbase.a.mask, [0, 0, 1, 1, 0])
        # 断言:确保mbase.b的掩码为指定数组
        assert_equal(mbase.b.mask, [1, 1, 0, 0, 0])
        # 断言:确保mbase.c的掩码为指定数组
        assert_equal(mbase.c.mask, [0, 0, 1, 1, 0])
    def test_set_elements(self):
        base = self.base.copy()
        # 复制基础数据结构并转换为记录数组视图,再次复制以确保修改不影响原始数据
        mbase = base.view(mrecarray).copy()
        # 将倒数第二行设置为掩码(masked)
        mbase[-2] = masked
        assert_equal(
            mbase._mask.tolist(),
            np.array([(0, 0, 0), (1, 1, 1), (0, 0, 0), (1, 1, 1), (1, 1, 1)],
                     dtype=bool))
        # 检查记录掩码(recordmask),预期为 [0, 1, 0, 1, 1]
        assert_equal(mbase.recordmask, [0, 1, 0, 1, 1])
        
        # 再次复制基础数据结构并转换为记录数组视图,设置前两行为元组 (5, 5, 5)
        mbase = base.view(mrecarray).copy()
        mbase[:2] = (5, 5, 5)
        # 检查字段 a 的数据部分,预期为 [5, 5, 3, 4, 5]
        assert_equal(mbase.a._data, [5, 5, 3, 4, 5])
        # 检查字段 a 的掩码部分,预期为 [0, 0, 0, 0, 1]
        assert_equal(mbase.a._mask, [0, 0, 0, 0, 1])
        # 检查字段 b 的数据部分,预期为 [5., 5., 3.3, 4.4, 5.5]
        assert_equal(mbase.b._data, [5., 5., 3.3, 4.4, 5.5])
        # 检查字段 b 的掩码部分,预期为 [0, 0, 0, 0, 1]
        assert_equal(mbase.b._mask, [0, 0, 0, 0, 1])
        # 检查字段 c 的数据部分,预期为 [b'5', b'5', b'three', b'four', b'five']
        assert_equal(mbase.c._data,
                     [b'5', b'5', b'three', b'four', b'five'])
        # 检查字段 b 的掩码部分,预期为 [0, 0, 0, 0, 1]
        assert_equal(mbase.b._mask, [0, 0, 0, 0, 1])

        # 再次复制基础数据结构并转换为记录数组视图,设置前两行为掩码(masked)
        mbase = base.view(mrecarray).copy()
        mbase[:2] = masked
        # 检查字段 a 的数据部分,预期为 [1, 2, 3, 4, 5]
        assert_equal(mbase.a._data, [1, 2, 3, 4, 5])
        # 检查字段 a 的掩码部分,预期为 [1, 1, 0, 0, 1]
        assert_equal(mbase.a._mask, [1, 1, 0, 0, 1])
        # 检查字段 b 的数据部分,预期为 [1.1, 2.2, 3.3, 4.4, 5.5]
        assert_equal(mbase.b._data, [1.1, 2.2, 3.3, 4.4, 5.5])
        # 检查字段 b 的掩码部分,预期为 [1, 1, 0, 0, 1]
        assert_equal(mbase.b._mask, [1, 1, 0, 0, 1])
        # 检查字段 c 的数据部分,预期为 [b'one', b'two', b'three', b'four', b'five']
        assert_equal(mbase.c._data,
                     [b'one', b'two', b'three', b'four', b'five'])
        # 检查字段 b 的掩码部分,预期为 [1, 1, 0, 0, 1]
        assert_equal(mbase.b._mask, [1, 1, 0, 0, 1])

    def test_setslices_hardmask(self):
        # 测试使用硬掩码设置切片
        base = self.base.copy()
        mbase = base.view(mrecarray)
        # 硬化掩码
        mbase.harden_mask()
        try:
            # 尝试设置倒数第二行及之后为元组 (5, 5, 5)
            mbase[-2:] = (5, 5, 5)
            # 检查字段 a 的数据部分,预期为 [1, 2, 3, 5, 5]
            assert_equal(mbase.a._data, [1, 2, 3, 5, 5])
            # 检查字段 b 的数据部分,预期为 [1.1, 2.2, 3.3, 5, 5.5]
            assert_equal(mbase.b._data, [1.1, 2.2, 3.3, 5, 5.5])
            # 检查字段 c 的数据部分,预期为 [b'one', b'two', b'three', b'5', b'five']
            assert_equal(mbase.c._data,
                         [b'one', b'two', b'three', b'5', b'five'])
            # 检查字段 a 的掩码部分,预期为 [0, 1, 0, 0, 1]
            assert_equal(mbase.a._mask, [0, 1, 0, 0, 1])
            # 检查字段 b 的掩码部分,预期与字段 a 相同
            assert_equal(mbase.b._mask, mbase.a._mask)
            # 检查字段 b 的掩码部分,预期与字段 a 相同
            assert_equal(mbase.b._mask, mbase.c._mask)
        except NotImplementedError:
            # 如果抛出未实现错误,捕获并忽略
            pass
        except AssertionError:
            # 如果断言错误,重新抛出异常
            raise
        else:
            # 如果没有抛出异常,抛出自定义异常
            raise Exception("Flexible hard masks should be supported !")
        
        # 尝试设置倒数第二行及之后为单个值 3,预期抛出类型错误
        try:
            mbase[-2:] = 3
        except (NotImplementedError, TypeError):
            # 如果抛出未实现错误或类型错误,捕获并忽略
            pass
        else:
            # 如果没有抛出预期的异常类型错误,抛出类型错误异常
            raise TypeError("Should have expected a readable buffer object!")
    def test_hardmask(self):
        # Test hardmask
        # 复制基础数据,并将其视为结构化数组
        base = self.base.copy()
        mbase = base.view(mrecarray)
        # 设置硬屏蔽
        mbase.harden_mask()
        # 断言硬屏蔽已开启
        assert_(mbase._hardmask)
        # 清除屏蔽
        mbase.mask = nomask
        # 断言记录屏蔽与基础的屏蔽相等
        assert_equal_records(mbase._mask, base._mask)
        # 变为软屏蔽
        mbase.soften_mask()
        # 断言硬屏蔽已关闭
        assert_(not mbase._hardmask)
        # 清除屏蔽
        mbase.mask = nomask
        # 所以,字段的屏蔽不再设置为 nomask...
        # 断言记录的屏蔽与基础形状、数据类型的全部屏蔽相等
        assert_equal_records(mbase._mask,
                             ma.make_mask_none(base.shape, base.dtype))
        # 断言 mbase['b'] 的屏蔽为 nomask
        assert_(ma.make_mask(mbase['b']._mask) is nomask)
        # 断言 mbase['a'] 的屏蔽与 mbase['b'] 的屏蔽相等
        assert_equal(mbase['a']._mask, mbase['b']._mask)

    def test_pickling(self):
        # Test pickling
        # 复制基础数据
        base = self.base.copy()
        # 将基础数据视为结构化数组
        mrec = base.view(mrecarray)
        # 对于从 2 到 pickle.HIGHEST_PROTOCOL + 1 的每个协议
        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
            # 使用指定协议序列化 mrec
            _ = pickle.dumps(mrec, protocol=proto)
            # 反序列化为 mrec_
            mrec_ = pickle.loads(_)
            # 断言 mrec_ 的数据类型与 mrec 相等
            assert_equal(mrec_.dtype, mrec.dtype)
            # 断言 mrec_ 的数据记录与 mrec 的数据记录相等
            assert_equal_records(mrec_._data, mrec._data)
            # 断言 mrec_ 的屏蔽与 mrec 的屏蔽相等
            assert_equal(mrec_._mask, mrec._mask)
            # 断言 mrec_ 的数据记录的屏蔽与 mrec 的数据记录的屏蔽相等
            assert_equal_records(mrec_._mask, mrec._mask)

    def test_filled(self):
        # Test filling the array
        # 创建带屏蔽的数组 _a, _b, _c
        _a = ma.array([1, 2, 3], mask=[0, 0, 1], dtype=int)
        _b = ma.array([1.1, 2.2, 3.3], mask=[0, 0, 1], dtype=float)
        _c = ma.array(['one', 'two', 'three'], mask=[0, 0, 1], dtype='|S8')
        # 定义结构化数组的数据类型 ddtype
        ddtype = [('a', int), ('b', float), ('c', '|S8')]
        # 使用 fromarrays 创建结构化数组 mrec,并指定填充值
        mrec = fromarrays([_a, _b, _c], dtype=ddtype,
                          fill_value=(99999, 99999., 'N/A'))
        # 获取填充后的结构化数组 mrecfilled
        mrecfilled = mrec.filled()
        # 断言填充后的 mrecfilled['a'] 与预期相等
        assert_equal(mrecfilled['a'], np.array((1, 2, 99999), dtype=int))
        # 断言填充后的 mrecfilled['b'] 与预期相等
        assert_equal(mrecfilled['b'], np.array((1.1, 2.2, 99999.),
                                               dtype=float))
        # 断言填充后的 mrecfilled['c'] 与预期相等
        assert_equal(mrecfilled['c'], np.array(('one', 'two', 'N/A'),
                                               dtype='|S8'))

    def test_tolist(self):
        # Test tolist.
        # 创建带屏蔽的数组 _a, _b, _c
        _a = ma.array([1, 2, 3], mask=[0, 0, 1], dtype=int)
        _b = ma.array([1.1, 2.2, 3.3], mask=[0, 0, 1], dtype=float)
        _c = ma.array(['one', 'two', 'three'], mask=[1, 0, 0], dtype='|S8')
        # 定义结构化数组的数据类型 ddtype
        ddtype = [('a', int), ('b', float), ('c', '|S8')]
        # 使用 fromarrays 创建结构化数组 mrec,并指定填充值
        mrec = fromarrays([_a, _b, _c], dtype=ddtype,
                          fill_value=(99999, 99999., 'N/A'))

        # 断言 mrec 转换为列表后与预期相等
        assert_equal(mrec.tolist(),
                     [(1, 1.1, None), (2, 2.2, b'two'),
                      (None, None, b'three')])

    def test_withnames(self):
        # Test the creation w/ format and names
        # 使用给定格式和名称创建结构化数组 x
        x = mrecarray(1, formats=float, names='base')
        # 设置第一个元素的 'base' 字段为 10
        x[0]['base'] = 10
        # 断言 x 的 'base' 字段第一个元素与预期相等
        assert_equal(x['base'][0], 10)
    # 定义测试函数 test_exotic_formats(self)
    def test_exotic_formats(self):
        # 测试处理“奇特”格式是否正确
        # 创建一个具有指定数据类型的结构化数组,包含整数、字节字符串和浮点数字段
        easy = mrecarray(1, dtype=[('i', int), ('s', '|S8'), ('f', float)])
        # 将数组的第一个元素设置为掩码值
        easy[0] = masked
        # 断言填充掩码后的数组元素是否符合预期值
        assert_equal(easy.filled(1).item(), (1, b'1', 1.))

        # 创建一个具有指定数据类型的结构化数组,包含一个名为 'f0' 的二维浮点数组字段
        solo = mrecarray(1, dtype=[('f0', '<f8', (2, 2))])
        # 将数组的第一个元素设置为掩码值
        solo[0] = masked
        # 断言填充掩码后的数组元素是否符合预期值
        assert_equal(solo.filled(1).item(),
                     np.array((1,), dtype=solo.dtype).item())

        # 创建一个具有复杂数据类型的结构化数组,包含整数、二维浮点数组和单个浮点数字段
        mult = mrecarray(2, dtype="i4, (2,3)float, float")
        # 将数组的第一个元素设置为掩码值
        mult[0] = masked
        # 设置数组的第二个元素为指定的值元组
        mult[1] = (1, 1, 1)
        # 调用 filled 方法填充数组中的掩码值
        mult.filled(0)
        # 断言填充掩码后的数组是否与预期数组相等
        assert_equal_records(mult.filled(0),
                             np.array([(0, 0, 0), (1, 1, 1)],
                                      dtype=mult.dtype))
class TestView:

    def setup_method(self):
        # 创建包含整数和随机浮点数的 NumPy 数组
        (a, b) = (np.arange(10), np.random.rand(10))
        # 定义数组的数据类型
        ndtype = [('a', float), ('b', float)]
        # 使用数据类型创建结构化数组
        arr = np.array(list(zip(a, b)), dtype=ndtype)

        # 使用 fromarrays 函数创建一个 MaskedRecords 对象
        mrec = fromarrays([a, b], dtype=ndtype, fill_value=(-9., -99.))
        # 将第三个元素的第二个字段标记为 True
        mrec.mask[3] = (False, True)
        # 将数据保存在实例变量中
        self.data = (mrec, a, b, arr)

    def test_view_by_itself(self):
        (mrec, a, b, arr) = self.data
        # 创建 mrec 的视图对象
        test = mrec.view()
        # 断言 test 是 MaskedRecords 类型的对象
        assert_(isinstance(test, MaskedRecords))
        # 断言 test 与 mrec 相等
        assert_equal_records(test, mrec)
        # 断言 test 的掩码与 mrec 的掩码相等
        assert_equal_records(test._mask, mrec._mask)

    def test_view_simple_dtype(self):
        (mrec, a, b, arr) = self.data
        # 定义一个简单的数据类型
        ntype = (float, 2)
        # 创建 mrec 的视图对象,使用指定的数据类型
        test = mrec.view(ntype)
        # 断言 test 是 ma.MaskedArray 类型的对象
        assert_(isinstance(test, ma.MaskedArray))
        # 断言 test 与 arr 相等,转换为指定的浮点数数据类型
        assert_equal(test, np.array(list(zip(a, b)), dtype=float))
        # 断言 test 的第四行第二列是掩码值
        assert_(test[3, 1] is ma.masked)

    def test_view_flexible_type(self):
        (mrec, a, b, arr) = self.data
        # 定义一个灵活的数据类型
        alttype = [('A', float), ('B', float)]
        # 创建 mrec 的视图对象,使用灵活的数据类型
        test = mrec.view(alttype)
        # 断言 test 是 MaskedRecords 类型的对象
        assert_(isinstance(test, MaskedRecords))
        # 断言 test 与 arr 的视图对象相等,使用指定的灵活数据类型
        assert_equal_records(test, arr.view(alttype))
        # 断言 test 的'B'字段的第四个元素是掩码值
        assert_(test['B'][3] is masked)
        # 断言 test 的数据类型与指定的灵活数据类型相等
        assert_equal(test.dtype, np.dtype(alttype))
        # 断言 test 的填充值为 None
        assert_(test._fill_value is None)


##############################################################################
class TestMRecordsImport:

    # 创建带有掩码的 ma.array 对象
    _a = ma.array([1, 2, 3], mask=[0, 0, 1], dtype=int)
    _b = ma.array([1.1, 2.2, 3.3], mask=[0, 0, 1], dtype=float)
    _c = ma.array([b'one', b'two', b'three'],
                  mask=[0, 0, 1], dtype='|S8')
    # 定义一个结构化数据类型
    ddtype = [('a', int), ('b', float), ('c', '|S8')]
    # 使用 fromarrays 函数创建 MaskedRecords 对象
    mrec = fromarrays([_a, _b, _c], dtype=ddtype,
                      fill_value=(b'99999', b'99999.',
                                  b'N/A'))
    # 使用 recfromarrays 函数创建记录数组对象
    nrec = recfromarrays((_a._data, _b._data, _c._data), dtype=ddtype)
    # 将数据保存在实例变量中
    data = (mrec, nrec, ddtype)

    def test_fromarrays(self):
        # 创建带有掩码的 ma.array 对象
        _a = ma.array([1, 2, 3], mask=[0, 0, 1], dtype=int)
        _b = ma.array([1.1, 2.2, 3.3], mask=[0, 0, 1], dtype=float)
        _c = ma.array(['one', 'two', 'three'], mask=[0, 0, 1], dtype='|S8')
        # 解包数据元组
        (mrec, nrec, _) = self.data
        # 遍历字段和其对应的 ma.array 对象
        for (f, l) in zip(('a', 'b', 'c'), (_a, _b, _c)):
            # 断言 mrec 中字段的掩码与相应的 ma.array 对象的掩码相等
            assert_equal(getattr(mrec, f)._mask, l._mask)
        # 创建只有一个记录的 ma.array 对象
        _x = ma.array([1, 1.1, 'one'], mask=[1, 0, 0], dtype=object)
        # 断言使用 fromarrays 函数创建的对象与 mrec 的第一个记录相等
        assert_equal_records(fromarrays(_x, dtype=mrec.dtype), mrec[0])
    def test_fromrecords(self):
        # Test construction from records.

        (mrec, nrec, ddtype) = self.data
        # 解包数据元组,获取测试数据 mrec, nrec, ddtype

        palist = [(1, 'abc', 3.7000002861022949, 0),
                  (2, 'xy', 6.6999998092651367, 1),
                  (0, ' ', 0.40000000596046448, 0)]
        # 定义一个包含多个记录的列表 palist

        pa = recfromrecords(palist, names='c1, c2, c3, c4')
        # 使用 recfromrecords 函数从 palist 中创建结构化数组 pa,并指定字段名

        mpa = fromrecords(palist, names='c1, c2, c3, c4')
        # 使用 fromrecords 函数从 palist 中创建结构化数组 mpa,并指定字段名

        assert_equal_records(pa, mpa)
        # 断言结构化数组 pa 和 mpa 相等

        _mrec = fromrecords(nrec)
        # 使用 fromrecords 函数从 nrec 中创建结构化数组 _mrec

        assert_equal(_mrec.dtype, mrec.dtype)
        # 断言 _mrec 的数据类型与 mrec 的数据类型相等

        for field in _mrec.dtype.names:
            assert_equal(getattr(_mrec, field), getattr(mrec._data, field))
        # 遍历 _mrec 的字段名,断言每个字段的属性值与 mrec 数据对象中对应字段的属性值相等

        _mrec = fromrecords(nrec.tolist(), names='c1,c2,c3')
        # 使用 fromrecords 函数从 nrec 转换成列表后,指定字段名创建结构化数组 _mrec

        assert_equal(_mrec.dtype, [('c1', int), ('c2', float), ('c3', '|S5')])
        # 断言 _mrec 的数据类型为包含字段 'c1', 'c2', 'c3' 的元组数组,分别指定为 int, float 和固定字节字符串

        for (f, n) in zip(('c1', 'c2', 'c3'), ('a', 'b', 'c')):
            assert_equal(getattr(_mrec, f), getattr(mrec._data, n))
        # 使用 zip 函数并结合 getattr 函数,断言 _mrec 中的字段值与 mrec 数据对象中对应字段的值相等

        _mrec = fromrecords(mrec)
        # 使用 fromrecords 函数直接从 mrec 创建结构化数组 _mrec

        assert_equal(_mrec.dtype, mrec.dtype)
        # 断言 _mrec 的数据类型与 mrec 的数据类型相等

        assert_equal_records(_mrec._data, mrec.filled())
        # 断言 _mrec 的数据部分与 mrec 的填充后数据部分相等

        assert_equal_records(_mrec._mask, mrec._mask)
        # 断言 _mrec 的掩码部分与 mrec 的掩码部分相等

    def test_fromrecords_wmask(self):
        # Tests construction from records w/ mask.

        (mrec, nrec, ddtype) = self.data
        # 解包数据元组,获取测试数据 mrec, nrec, ddtype

        _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=[0, 1, 0,])
        # 使用 fromrecords 函数从 nrec 转换成列表后,指定数据类型 ddtype,并指定掩码创建结构化数组 _mrec

        assert_equal_records(_mrec._data, mrec._data)
        # 断言 _mrec 的数据部分与 mrec 的数据部分相等

        assert_equal(_mrec._mask.tolist(), [(0, 0, 0), (1, 1, 1), (0, 0, 0)])
        # 断言 _mrec 的掩码部分与指定的掩码列表相等

        _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=True)
        # 使用 fromrecords 函数从 nrec 转换成列表后,指定数据类型 ddtype,并使用 True 作为掩码创建结构化数组 _mrec

        assert_equal_records(_mrec._data, mrec._data)
        # 断言 _mrec 的数据部分与 mrec 的数据部分相等

        assert_equal(_mrec._mask.tolist(), [(1, 1, 1), (1, 1, 1), (1, 1, 1)])
        # 断言 _mrec 的掩码部分全为 True

        _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=mrec._mask)
        # 使用 fromrecords 函数从 nrec 转换成列表后,指定数据类型 ddtype,并使用 mrec 的掩码创建结构化数组 _mrec

        assert_equal_records(_mrec._data, mrec._data)
        # 断言 _mrec 的数据部分与 mrec 的数据部分相等

        assert_equal(_mrec._mask.tolist(), mrec._mask.tolist())
        # 断言 _mrec 的掩码部分与 mrec 的掩码部分相等

        _mrec = fromrecords(nrec.tolist(), dtype=ddtype,
                            mask=mrec._mask.tolist())
        # 使用 fromrecords 函数从 nrec 转换成列表后,指定数据类型 ddtype,并使用 mrec 的掩码列表创建结构化数组 _mrec

        assert_equal_records(_mrec._data, mrec._data)
        # 断言 _mrec 的数据部分与 mrec 的数据部分相等

        assert_equal(_mrec._mask.tolist(), mrec._mask.tolist())
        # 断言 _mrec 的掩码部分与 mrec 的掩码部分相等

    def test_fromtextfile(self):
        # Tests reading from a text file.
        
        fcontent = (
# 定义一个测试类 TestMaskedRecords,用于测试 MaskedRecords 相关功能
class TestMaskedRecords(TestCase):

    # 测试从文本文件读取并生成 MaskedRecords 对象的功能
    def test_fromtextfile(self):
        # 定义测试用的文本内容
        fcontent = (
            """#
            'One (S)','Two (I)','Three (F)','Four (M)','Five (-)','Six (C)'
            'strings',1,1.0,'mixed column',,1
            'with embedded "double quotes"',2,2.0,1.0,,1
            'strings',3,3.0E5,3,,1
            'strings',4,-1e-10,,,1
            """)
        # 创建临时文件路径,将文本内容写入文件
        with temppath() as path:
            with open(path, 'w') as f:
                f.write(fcontent)
            # 调用 fromtextfile 函数,从文件中读取数据并生成 MaskedRecords 对象
            mrectxt = fromtextfile(path, delimiter=',', varnames='ABCDEFG')
        # 断言 mrectxt 是 MaskedRecords 类型的对象
        assert_(isinstance(mrectxt, MaskedRecords))
        # 断言 mrectxt 中属性 F 的值与预期列表相等
        assert_equal(mrectxt.F, [1, 1, 1, 1])
        # 断言 mrectxt 中属性 E 的掩码(mask)与预期列表相等
        assert_equal(mrectxt.E._mask, [1, 1, 1, 1])
        # 断言 mrectxt 中属性 C 的值与预期列表相等
        assert_equal(mrectxt.C, [1, 2, 3.e+5, -1e-10])

    # 测试向 MaskedRecords 对象添加新字段的功能
    def test_addfield(self):
        # 获取测试数据
        (mrec, nrec, ddtype) = self.data
        (d, m) = ([100, 200, 300], [1, 0, 0])
        # 向 mrec 对象添加新字段,字段值为数组 d,掩码为数组 m
        mrec = addfield(mrec, ma.array(d, mask=m))
        # 断言 mrec 中新添加的字段 f3 的值与数组 d 相等
        assert_equal(mrec.f3, d)
        # 断言 mrec 中新添加的字段 f3 的掩码与数组 m 相等
        assert_equal(mrec.f3._mask, m)


def test_record_array_with_object_field():
    # Trac #1839
    # 创建一个具有对象字段的 MaskedArray 对象 y
    y = ma.masked_array(
        [(1, '2'), (3, '4')],
        mask=[(0, 0), (0, 1)],
        dtype=[('a', int), ('b', object)])
    # 尝试获取 y 的第二个元素,以前此操作会失败
    y[1]

.\numpy\numpy\ma\tests\test_old_ma.py

# 导入 reduce 函数用于累积计算,pickle 用于对象序列化
from functools import reduce
import pickle

# 导入 pytest 测试框架
import pytest

# 导入 numpy 库及其子模块
import numpy as np
import numpy._core.umath as umath
import numpy._core.fromnumeric as fromnumeric

# 导入 numpy.testing 模块下的各种断言函数
from numpy.testing import (
    assert_, assert_raises, assert_equal,
    )

# 导入 numpy.ma 模块下的函数和类
from numpy.ma import (
    MaskType, MaskedArray, absolute, add, all, allclose, allequal, alltrue,
    arange, arccos, arcsin, arctan, arctan2, array, average, choose,
    concatenate, conjugate, cos, cosh, count, divide, equal, exp, filled,
    getmask, greater, greater_equal, inner, isMaskedArray, less,
    less_equal, log, log10, make_mask, masked, masked_array, masked_equal,
    masked_greater, masked_greater_equal, masked_inside, masked_less,
    masked_less_equal, masked_not_equal, masked_outside,
    masked_print_option, masked_values, masked_where, maximum, minimum,
    multiply, nomask, nonzero, not_equal, ones, outer, product, put, ravel,
    repeat, resize, shape, sin, sinh, sometrue, sort, sqrt, subtract, sum,
    take, tan, tanh, transpose, where, zeros,
    )

# 设置 pi 的值为 numpy 中的圆周率常量
pi = np.pi

# 自定义函数 eq,用于比较两个值或数组是否近似相等
def eq(v, w, msg=''):
    # 使用 numpy 的 allclose 函数判断两个数组或值是否近似相等
    result = allclose(v, w)
    # 如果不相等,则打印消息和不相等的值,并返回 False;否则返回 True
    if not result:
        print(f'Not eq:{msg}\n{v}\n----{w}')
    return result

# 定义一个测试类 TestMa
class TestMa:

    # 初始化方法,在每个测试方法运行之前被调用,设置测试数据
    def setup_method(self):
        # 初始化测试数据
        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.])
        a10 = 10.
        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 = array(x, mask=m1)  # 创建一个带有掩码的 MaskedArray 对象 xm
        ym = array(y, mask=m2)  # 创建一个带有掩码的 MaskedArray 对象 ym
        z = np.array([-.5, 0., .5, .8])
        zm = array(z, mask=[0, 1, 0, 0])  # 创建一个带有掩码的 MaskedArray 对象 zm
        xf = np.where(m1, 1e+20, x)  # 根据掩码 m1 条件填充数组 x 中的元素
        s = x.shape  # 获取数组 x 的形状
        xm.set_fill_value(1e+20)  # 设置 MaskedArray xm 的填充值
        self.d = (x, y, a10, m1, m2, xm, ym, z, zm, xf, s)  # 将数据存储在实例属性 d 中

    # 测试方法,用于测试在 1 维情况下的基本数组创建和属性
    def test_testBasic1d(self):
        # 获取初始化设置的测试数据
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        assert_(not isMaskedArray(x))  # 断言 x 不是 MaskedArray 对象
        assert_(isMaskedArray(xm))  # 断言 xm 是 MaskedArray 对象
        assert_equal(shape(xm), s)  # 断言 xm 的形状与 s 相等
        assert_equal(xm.shape, s)  # 断言 xm 的形状与 s 相等
        assert_equal(xm.dtype, x.dtype)  # 断言 xm 的数据类型与 x 相等
        assert_equal(xm.size, reduce(lambda x, y:x * y, s))  # 断言 xm 的大小与 s 元素数的乘积相等
        assert_equal(count(xm), len(m1) - reduce(lambda x, y:x + y, m1))  # 断言 xm 中非掩码元素的数量
        assert_(eq(xm, xf))  # 断言 xm 与填充后的 xf 近似相等
        assert_(eq(filled(xm, 1.e20), xf))  # 断言填充值为 1.e20 后的 xm 与 xf 近似相等
        assert_(eq(x, xm))  # 断言 x 与 xm 近似相等

    @pytest.mark.parametrize("s", [(4, 3), (6, 2)])
    def test_testBasic2d(self, s):
        # Test of basic array creation and properties in 2 dimensions.
        # 解包测试数据元组
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        # 设置数组 x, y, xm, ym, xf 的形状为 s
        x.shape = s
        y.shape = s
        xm.shape = s
        ym.shape = s
        xf.shape = s

        # 断言 x 不是 MaskedArray
        assert_(not isMaskedArray(x))
        # 断言 xm 是 MaskedArray
        assert_(isMaskedArray(xm))
        # 断言 xm 的形状等于 s
        assert_equal(shape(xm), s)
        # 断言 xm 的形状等于 s
        assert_equal(xm.shape, s)
        # 断言 xm 的大小等于 s 元素数的乘积
        assert_equal(xm.size, reduce(lambda x, y: x * y, s))
        # 断言 xm 中填充的值个数等于 m1 中未填充值的个数
        assert_equal(count(xm), len(m1) - reduce(lambda x, y: x + y, m1))
        # 断言 xm 和 xf 相等
        assert_(eq(xm, xf))
        # 断言 xm 和填充值为 1.e20 的 xf 相等
        assert_(eq(filled(xm, 1.e20), xf))
        # 断言 x 和 xm 相等
        assert_(eq(x, xm))

    def test_testArithmetic(self):
        # Test of basic arithmetic.
        # 解包测试数据元组
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        # 创建一个二维数组 a2d
        a2d = array([[1, 2], [0, 4]])
        # 使用 a2d 创建一个带掩码的数组 a2dm
        a2dm = masked_array(a2d, [[0, 0], [1, 0]])
        # 断言 a2d 和 a2dm 的乘法结果相等
        assert_(eq(a2d * a2d, a2d * a2dm))
        # 断言 a2d 和 a2dm 的加法结果相等
        assert_(eq(a2d + a2d, a2d + a2dm))
        # 断言 a2d 和 a2dm 的减法结果相等
        assert_(eq(a2d - a2d, a2d - a2dm))

        # 遍历不同的形状 s 进行测试
        for s in [(12,), (4, 3), (2, 6)]:
            # 重塑数组 x, y, xm, ym, xf 的形状为 s
            x = x.reshape(s)
            y = y.reshape(s)
            xm = xm.reshape(s)
            ym = ym.reshape(s)
            xf = xf.reshape(s)
            # 断言 x 的相反数等于 xm 的相反数
            assert_(eq(-x, -xm))
            # 断言 x 和 y 的加法结果等于 xm 和 ym 的加法结果
            assert_(eq(x + y, xm + ym))
            # 断言 x 和 y 的减法结果等于 xm 和 ym 的减法结果
            assert_(eq(x - y, xm - ym))
            # 断言 x 和 y 的乘法结果等于 xm 和 ym 的乘法结果
            assert_(eq(x * y, xm * ym))
            # 使用忽略除零和无效的错误状态,断言 x 和 y 的除法结果等于 xm 和 ym 的除法结果
            with np.errstate(divide='ignore', invalid='ignore'):
                assert_(eq(x / y, xm / ym))
            # 断言 a10 和 y 的加法结果等于 a10 和 ym 的加法结果
            assert_(eq(a10 + y, a10 + ym))
            # 断言 a10 和 y 的减法结果等于 a10 和 ym 的减法结果
            assert_(eq(a10 - y, a10 - ym))
            # 断言 a10 和 y 的乘法结果等于 a10 和 ym 的乘法结果
            assert_(eq(a10 * y, a10 * ym))
            # 使用忽略除零和无效的错误状态,断言 a10 和 y 的除法结果等于 a10 和 ym 的除法结果
            with np.errstate(divide='ignore', invalid='ignore'):
                assert_(eq(a10 / y, a10 / ym))
            # 断言 x 和 a10 的加法结果等于 xm 和 a10 的加法结果
            assert_(eq(x + a10, xm + a10))
            # 断言 x 和 a10 的减法结果等于 xm 和 a10 的减法结果
            assert_(eq(x - a10, xm - a10))
            # 断言 x 和 a10 的乘法结果等于 xm 和 a10 的乘法结果
            assert_(eq(x * a10, xm * a10))
            # 断言 x 和 a10 的除法结果等于 xm 和 a10 的除法结果
            assert_(eq(x / a10, xm / a10))
            # 断言 x 的平方结果等于 xm 的平方结果
            assert_(eq(x ** 2, xm ** 2))
            # 断言 x 的绝对值的2.5次方等于 xm 的绝对值的2.5次方
            assert_(eq(abs(x) ** 2.5, abs(xm) ** 2.5))
            # 断言 x 的 y 次方结果等于 xm 的 ym 次方结果
            assert_(eq(x ** y, xm ** ym))
            # 断言 np.add(x, y) 的结果等于 add(xm, ym) 的结果
            assert_(eq(np.add(x, y), add(xm, ym)))
            # 断言 np.subtract(x, y) 的结果等于 subtract(xm, ym) 的结果
            assert_(eq(np.subtract(x, y), subtract(xm, ym)))
            # 断言 np.multiply(x, y) 的结果等于 multiply(xm, ym) 的结果
            assert_(eq(np.multiply(x, y), multiply(xm, ym)))
            # 使用忽略除零和无效的错误状态,断言 np.divide(x, y) 的结果等于 divide(xm, ym) 的结果
            with np.errstate(divide='ignore', invalid='ignore'):
                assert_(eq(np.divide(x, y), divide(xm, ym)))

    def test_testMixedArithmetic(self):
        # Test of mixed arithmetic operations between ndarray and MaskedArray.
        # 创建一个包含单个元素 1 的 ndarray 对象 na
        na = np.array([1])
        # 创建一个包含单个元素 1 的 MaskedArray 对象 ma
        ma = array([1])
        # 断言 na 和 ma 的加法结果是 MaskedArray 类型
        assert_(isinstance(na + ma, MaskedArray))
        # 断言 ma 和 na 的加法结果是 MaskedArray 类型
        assert_(isinstance(ma + na, MaskedArray))
    def test_testUfuncs1(self):
        # 测试各种函数,如 sin、cos 等。
        # 从元组 self.d 中获取变量 x, y, a10, m1, m2, xm, ym, z, zm, xf, s
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        
        # 断言 np.cos(x) 等于 cos(xm)
        assert_(eq(np.cos(x), cos(xm)))
        # 断言 np.cosh(x) 等于 cosh(xm)
        assert_(eq(np.cosh(x), cosh(xm)))
        # 断言 np.sin(x) 等于 sin(xm)
        assert_(eq(np.sin(x), sin(xm)))
        # 断言 np.sinh(x) 等于 sinh(xm)
        assert_(eq(np.sinh(x), sinh(xm)))
        # 断言 np.tan(x) 等于 tan(xm)
        assert_(eq(np.tan(x), tan(xm)))
        # 断言 np.tanh(x) 等于 tanh(xm)
        assert_(eq(np.tanh(x), tanh(xm)))
        
        # 忽略除零和无效值的错误状态
        with np.errstate(divide='ignore', invalid='ignore'):
            # 断言 np.sqrt(abs(x)) 等于 sqrt(xm)
            assert_(eq(np.sqrt(abs(x)), sqrt(xm)))
            # 断言 np.log(abs(x)) 等于 log(xm)
            assert_(eq(np.log(abs(x)), log(xm)))
            # 断言 np.log10(abs(x)) 等于 log10(xm)
            assert_(eq(np.log10(abs(x)), log10(xm)))
        
        # 断言 np.exp(x) 等于 exp(xm)
        assert_(eq(np.exp(x), exp(xm)))
        # 断言 np.arcsin(z) 等于 arcsin(zm)
        assert_(eq(np.arcsin(z), arcsin(zm)))
        # 断言 np.arccos(z) 等于 arccos(zm)
        assert_(eq(np.arccos(z), arccos(zm)))
        # 断言 np.arctan(z) 等于 arctan(zm)
        assert_(eq(np.arctan(z), arctan(zm)))
        # 断言 np.arctan2(x, y) 等于 arctan2(xm, ym)
        assert_(eq(np.arctan2(x, y), arctan2(xm, ym)))
        # 断言 np.absolute(x) 等于 absolute(xm)
        assert_(eq(np.absolute(x), absolute(xm)))
        # 断言 np.equal(x, y) 等于 equal(xm, ym)
        assert_(eq(np.equal(x, y), equal(xm, ym)))
        # 断言 np.not_equal(x, y) 等于 not_equal(xm, ym)
        assert_(eq(np.not_equal(x, y), not_equal(xm, ym)))
        # 断言 np.less(x, y) 等于 less(xm, ym)
        assert_(eq(np.less(x, y), less(xm, ym)))
        # 断言 np.greater(x, y) 等于 greater(xm, ym)
        assert_(eq(np.greater(x, y), greater(xm, ym)))
        # 断言 np.less_equal(x, y) 等于 less_equal(xm, ym)
        assert_(eq(np.less_equal(x, y), less_equal(xm, ym)))
        # 断言 np.greater_equal(x, y) 等于 greater_equal(xm, ym)
        assert_(eq(np.greater_equal(x, y), greater_equal(xm, ym)))
        # 断言 np.conjugate(x) 等于 conjugate(xm)
        assert_(eq(np.conjugate(x), conjugate(xm)))
        # 断言 np.concatenate((x, y)) 等于 concatenate((xm, ym))
        assert_(eq(np.concatenate((x, y)), concatenate((xm, ym))))
        # 断言 np.concatenate((x, y)) 等于 concatenate((x, y))
        assert_(eq(np.concatenate((x, y)), concatenate((x, y))))
        # 断言 np.concatenate((x, y)) 等于 concatenate((xm, y))
        assert_(eq(np.concatenate((x, y)), concatenate((xm, y))))
        # 断言 np.concatenate((x, y, x)) 等于 concatenate((x, ym, x))
        assert_(eq(np.concatenate((x, y, x)), concatenate((x, ym, x))))

    def test_xtestCount(self):
        # 测试计数功能
        # 创建一个 array ott,包含数值 [0., 1., 2., 3.],并设定部分元素被屏蔽(mask=[1, 0, 0, 0])
        ott = array([0., 1., 2., 3.], mask=[1, 0, 0, 0])
        
        # 断言 count(ott) 的 dtype 是 np.intp 类型
        assert_(count(ott).dtype.type is np.intp)
        # 断言 count(ott) 的结果为 3
        assert_equal(3, count(ott))
        # 断言 count(1) 的结果为 1
        assert_equal(1, count(1))
        # 断言 array(1, mask=[1]) 的结果等于 0
        assert_(eq(0, array(1, mask=[1])))
        
        # 将 ott 重新调整为形状为 (2, 2)
        ott = ott.reshape((2, 2))
        # 断言 count(ott) 的 dtype 是 np.intp 类型
        assert_(count(ott).dtype.type is np.intp)
        # 断言 count(ott, 0) 返回的类型是 np.ndarray
        assert_(isinstance(count(ott, 0), np.ndarray))
        # 断言 count(ott) 的 dtype 是 np.intp 类型
        assert_(count(ott).dtype.type is np.intp)
        # 断言 count(ott) 的结果为 3
        assert_(eq(3, count(ott)))
        # 断言 count(ott, 0) 的 mask 为 nomask
        assert_(getmask(count(ott, 0)) is nomask)
        # 断言 count(ott, 0) 的结果为 [1, 2]
        assert_(eq([1, 2], count(ott, 0)))

    def test_testMinMax(self):
        # 测试最小值和最大值
        # 从元组 self.d 中获取变量 x, y, a10, m1, m2, xm, ym, z, zm, xf, s
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        
        # 将 x 扁平化为 xr(如果形状不同,max 将无法正常工作)
        xr = np.ravel(x)
        # 将 xm 扁平化为 xmr
        xmr = ravel(xm)
        
        # 断言 max(xr) 等于 maximum.reduce(xmr)
        assert_(eq(max(xr), maximum.reduce(xmr)))
        # 断言 min(xr) 等于 minimum.reduce(xmr))
        assert_(eq(min(xr), minimum.reduce(xmr)))
    def test_testAddSumProd(self):
        # Test add, sum, product.
        # 从测试数据集中获取变量(x, y, a10, m1, m2, xm, ym, z, zm, xf, s)
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        # 断言:numpy 的 add.reduce 和自定义的 add.reduce 的结果相等
        assert_(eq(np.add.reduce(x), add.reduce(x)))
        # 断言:numpy 的 add.accumulate 和自定义的 add.accumulate 的结果相等
        assert_(eq(np.add.accumulate(x), add.accumulate(x)))
        # 断言:对 array(4) 沿着 axis=0 的求和结果等于 4
        assert_(eq(4, sum(array(4), axis=0)))
        # 断言:对 array(4) 沿着 axis=0 的求和结果等于 4
        assert_(eq(4, sum(array(4), axis=0)))
        # 断言:numpy 的 sum 函数和自定义的 sum 函数结果相等,沿着 axis=0
        assert_(eq(np.sum(x, axis=0), sum(x, axis=0)))
        # 断言:numpy 的 sum 函数和自定义的 sum 函数结果相等,对填充了 0 的 xm,沿着 axis=0
        assert_(eq(np.sum(filled(xm, 0), axis=0), sum(xm, axis=0)))
        # 断言:numpy 的 sum 函数和自定义的 sum 函数结果相等,沿着 axis=0
        assert_(eq(np.sum(x, 0), sum(x, 0)))
        # 断言:numpy 的 prod 函数和自定义的 product 函数结果相等,沿着 axis=0
        assert_(eq(np.prod(x, axis=0), product(x, axis=0)))
        # 断言:numpy 的 prod 函数和自定义的 product 函数结果相等,沿着 axis=0
        assert_(eq(np.prod(x, 0), product(x, 0)))
        # 断言:numpy 的 prod 函数和自定义的 product 函数结果相等,对填充了 1 的 xm,沿着 axis=0
        assert_(eq(np.prod(filled(xm, 1), axis=0),
                           product(xm, axis=0)))
        # 如果 s 的长度大于 1,则执行以下断言
        if len(s) > 1:
            # 断言:numpy 的 concatenate 函数和自定义的 concatenate 函数结果相等,沿着 axis=1
            assert_(eq(np.concatenate((x, y), 1),
                               concatenate((xm, ym), 1)))
            # 断言:numpy 的 add.reduce 函数和自定义的 add.reduce 函数结果相等,沿着 axis=1
            assert_(eq(np.add.reduce(x, 1), add.reduce(x, 1)))
            # 断言:numpy 的 sum 函数和自定义的 sum 函数结果相等,沿着 axis=1
            assert_(eq(np.sum(x, 1), sum(x, 1)))
            # 断言:numpy 的 prod 函数和自定义的 product 函数结果相等,沿着 axis=1
            assert_(eq(np.prod(x, 1), product(x, 1)))

    def test_testCI(self):
        # Test of conversions and indexing
        # 创建一个 numpy 数组 x1
        x1 = np.array([1, 2, 4, 3])
        # 使用带有屏蔽值的 array 函数创建数组 x2
        x2 = array(x1, mask=[1, 0, 0, 0])
        # 使用带有屏蔽值的 array 函数创建数组 x3
        x3 = array(x1, mask=[0, 1, 0, 1])
        # 使用 str 函数测试将 x2 转换为字符串,可能会引发异常
        str(x2)  # raises?
        # 使用 repr 函数测试将 x2 转换为字符串,可能会引发异常
        repr(x2)  # raises?
        # 断言:numpy 的 sort 函数和自定义的 sort 函数结果相等,对 x1 排序,使用 fill_value=0
        assert_(eq(np.sort(x1), sort(x2, fill_value=0)))
        # 断言:检查索引后的类型是否相等
        assert_(type(x2[1]) is type(x1[1]))
        # 断言:检查索引后的值是否相等
        assert_(x1[1] == x2[1])
        # 断言:检查 x2 的第一个元素是否为屏蔽值
        assert_(x2[0] is masked)
        # 断言:检查索引后的值是否相等
        assert_(eq(x1[2], x2[2]))
        # 断言:检查切片后的值是否相等
        assert_(eq(x1[2:5], x2[2:5]))
        # 断言:检查全切片后的值是否相等
        assert_(eq(x1[:], x2[:]))
        # 断言:检查 x1 和 x2 的第 1 到第 3 个元素是否相等
        assert_(eq(x1[1:3], x2[1:3]))
        # 修改 x1 和 x2 的第 2 个元素为 9,并断言它们相等
        x1[2] = 9
        x2[2] = 9
        assert_(eq(x1, x2))
        # 将 x1 和 x2 的第 1 到第 3 个元素修改为 99,并断言它们相等
        x1[1:3] = 99
        x2[1:3] = 99
        assert_(eq(x1, x2))
        # 将 x2 的第 2 个元素设为屏蔽值,并断言它们相等
        x2[1] = masked
        assert_(eq(x1, x2))
        # 将 x2 的第 1 到第 3 个元素设为屏蔽值,并断言它们相等
        x2[1:3] = masked
        assert_(eq(x1, x2))
        # 将 x2 的所有元素设为 x1 的值,并将第 2 个元素设为屏蔽值,并断言屏蔽数组的形状为 (0,)
        x2[:] = x1
        x2[1] = masked
        assert_(allequal(getmask(x2), array([0, 1, 0, 0])))
        # 将 x3 的所有元素设为带有屏蔽值的数组,并断言屏蔽数组的形状为 (0, 1, 1, 0)
        x3[:] = masked_array([1, 2, 3, 4], [0, 1, 1, 0])
        assert_(allequal(getmask(x3), array([0, 1, 1, 0])))
        # 将 x4 的所有元素设为带有屏蔽值的数组,并断言它们相等
        x4[:] = masked_array([1, 2, 3, 4], [0, 1, 1, 0])
        assert_(allequal(getmask(x4), array([0, 1, 1, 0])))
        assert_(allequal(x4, array([1, 2, 3, 4])))
        # 创建一个 numpy 数组 x1,数据类型为 object
        x1 = array([1, 'hello', 2, 3], object)
        # 创建一个 numpy 数组 x2,数据类型为 object
        x2 = np.array([1, 'hello', 2, 3], object)
        # 获取 x1 和 x2 的第 1 个元素
        s1 = x1[1]
        s2 = x2[1]
        # 断言:获取的 s1 和 s2 的类型为字符串
        assert_equal(type(s2), str)
        assert_equal(type(s1), str)
        # 断言:获取的 s1 和 s2 的值相等
        assert_equal(s1, s2)
        # 断言:切片 x1 的索引 1 到 1 的形状为 (0,)
        assert_(x1[1:1].shape == (0,))
    def test_testCopySize(self):
        # Tests of some subtle points of copying and sizing.

        # 创建一个包含五个元素的列表
        n = [0, 0, 1, 0, 0]
        # 调用 make_mask 函数创建掩码数组 m
        m = make_mask(n)
        # 将 m 作为参数再次调用 make_mask 函数,返回值赋给 m2
        m2 = make_mask(m)
        # 断言 m 和 m2 引用的是同一个对象
        assert_(m is m2)
        # 使用 copy=True 参数再次调用 make_mask 函数,返回值赋给 m3
        m3 = make_mask(m, copy=True)
        # 断言 m 和 m3 引用的不是同一个对象
        assert_(m is not m3)

        # 创建一个包含 0 到 4 的一维数组 x1
        x1 = np.arange(5)
        # 使用掩码 m 创建一个 MaskedArray 对象 y1
        y1 = array(x1, mask=m)
        # 断言 y1 的数据不是 x1
        assert_(y1._data is not x1)
        # 断言 y1 的数据和 x1 的数据相等
        assert_(allequal(x1, y1._data))
        # 断言 y1 的掩码属性是 m
        assert_(y1._mask is m)

        # 使用 copy=0 参数创建一个新的 MaskedArray 对象 y1a
        y1a = array(y1, copy=0)
        # 断言 y1a 的掩码的数组接口和 y1 的掩码的数组接口相等
        assert_(y1a._mask.__array_interface__ ==
                y1._mask.__array_interface__)

        # 使用 copy=0 和 m3 参数创建一个新的 MaskedArray 对象 y2
        y2 = array(x1, mask=m3, copy=0)
        # 断言 y2 的掩码是 m3
        assert_(y2._mask is m3)
        # 断言 y2 的第二个元素是 masked
        assert_(y2[2] is masked)
        # 修改 y2 的第二个元素为 9
        y2[2] = 9
        # 断言 y2 的第二个元素不是 masked
        assert_(y2[2] is not masked)
        # 断言 y2 的掩码是 m3
        assert_(y2._mask is m3)
        # 断言 y2 的所有掩码元素都是 0
        assert_(allequal(y2.mask, 0))

        # 使用 copy=1 和 m 参数创建一个新的 MaskedArray 对象 y2a
        y2a = array(x1, mask=m, copy=1)
        # 断言 y2a 的掩码不是 m
        assert_(y2a._mask is not m)
        # 断言 y2a 的第二个元素是 masked
        assert_(y2a[2] is masked)
        # 修改 y2a 的第二个元素为 9
        y2a[2] = 9
        # 断言 y2a 的第二个元素不是 masked
        assert_(y2a[2] is not masked)
        # 断言 y2a 的掩码不是 m
        assert_(y2a._mask is not m)
        # 断言 y2a 的所有掩码元素都是 0
        assert_(allequal(y2a.mask, 0))

        # 创建一个包含浮点数的一维数组 y3,数据与 x1 的数据相同,掩码为 m
        y3 = array(x1 * 1.0, mask=m)
        # 断言 filled(y3) 的数据类型与 (x1 * 1.0) 的数据类型相同
        assert_(filled(y3).dtype is (x1 * 1.0).dtype)

        # 创建一个一维数组 x4 包含四个元素
        x4 = arange(4)
        # 将 x4 的第三个元素设为 masked
        x4[2] = masked
        # 调整 x4 的大小为 (8,),赋给 y4
        y4 = resize(x4, (8,))
        # 断言 concatenate([x4, x4]) 等于 y4
        assert_(eq(concatenate([x4, x4]), y4))
        # 断言 y4 的掩码为 [0, 0, 1, 0, 0, 0, 1, 0]
        assert_(eq(getmask(y4), [0, 0, 1, 0, 0, 0, 1, 0]))
        # 将 x4 沿轴 0 重复 [2, 2, 2, 2],赋给 y5
        y5 = repeat(x4, (2, 2, 2, 2), axis=0)
        # 断言 y5 等于 [0, 0, 1, 1, 2, 2, 3, 3]
        assert_(eq(y5, [0, 0, 1, 1, 2, 2, 3, 3]))
        # 将 x4 沿轴 0 重复 2 次,赋给 y6
        y6 = repeat(x4, 2, axis=0)
        # 断言 y5 等于 y6
        assert_(eq(y5, y6))

    def test_testPut(self):
        # Test of put

        # 创建一个包含五个元素的一维数组 d
        d = arange(5)
        # 创建一个包含 [0, 0, 0, 1, 1] 的列表,赋给 n
        n = [0, 0, 0, 1, 1]
        # 调用 make_mask 函数创建掩码数组 m
        m = make_mask(n)
        # 复制 m,并赋给 m2
        m2 = m.copy()
        # 使用 m 创建一个 MaskedArray 对象 x
        x = array(d, mask=m)
        # 断言 x 的第四个元素是 masked
        assert_(x[3] is masked)
        # 断言 x 的第五个元素是 masked
        assert_(x[4] is masked)
        # 将 x 的第二个和第五个元素分别设为 10 和 40
        x[[1, 4]] = [10, 40]
        # 断言 x 的掩码是 m
        assert_(x._mask is m)
        # 断言 x 的第四个元素是 masked
        assert_(x[3] is masked)
        # 断言 x 的第五个元素不是 masked
        assert_(x[4] is not masked)
        # 断言 x 的元素与 [0, 10, 2, -1, 40] 相等
        assert_(eq(x, [0, 10, 2, -1, 40]))

        # 使用 copy=True 和 m2 创建一个新的 MaskedArray 对象 x
        x = array(d, mask=m2, copy=True)
        # 使用 put 方法将 [-1, 100, 200] 分别放置在 x 的第一个、第二个和第三个位置
        x.put([0, 1, 2], [-1, 100, 200])
        # 断言 x 的掩码不是 m2
        assert_(x._mask is not m2)
        # 断言 x 的第四个元素是 masked
        assert_(x[3] is masked)
        # 断言 x 的第五个元素是 masked
        assert_(x[4] is masked)
        # 断言 x 的元素与 [-1, 100, 200, 0, 0] 相等
        assert_(eq(x, [-1, 100, 200, 0, 0]))
    def test_testPut2(self):
        # Test of put
        # 创建一个包含0到4的数组
        d = arange(5)
        # 创建一个带有掩码的数组,掩码表明所有元素都未被屏蔽
        x = array(d, mask=[0, 0, 0, 0, 0])
        # 创建另一个带有掩码的数组,其中第一个元素被屏蔽
        z = array([10, 40], mask=[1, 0])
        # 断言:x的第2个元素未被屏蔽
        assert_(x[2] is not masked)
        # 断言:x的第3个元素未被屏蔽
        assert_(x[3] is not masked)
        # 将z的值放入x的第2到第4个位置
        x[2:4] = z
        # 断言:x的第2个元素已被屏蔽
        assert_(x[2] is masked)
        # 断言:x的第3个元素未被屏蔽
        assert_(x[3] is not masked)
        # 断言:x是否等于[0, 1, 10, 40, 4]
        assert_(eq(x, [0, 1, 10, 40, 4]))

        # 重新初始化变量d和x,重复上述步骤,但不修改原始数组x
        d = arange(5)
        x = array(d, mask=[0, 0, 0, 0, 0])
        # 从x中获取第2到第4个元素形成一个新的数组y
        y = x[2:4]
        # 创建另一个带有掩码的数组z
        z = array([10, 40], mask=[1, 0])
        # 断言:x的第2个元素未被屏蔽
        assert_(x[2] is not masked)
        # 断言:x的第3个元素未被屏蔽
        assert_(x[3] is not masked)
        # 将z的值放入y中
        y[:] = z
        # 断言:y的第一个元素已被屏蔽
        assert_(y[0] is masked)
        # 断言:y的第二个元素未被屏蔽
        assert_(y[1] is not masked)
        # 断言:y是否等于[10, 40]
        assert_(eq(y, [10, 40]))
        # 断言:x的第2个元素已被屏蔽
        assert_(x[2] is masked)
        # 断言:x的第3个元素未被屏蔽
        assert_(x[3] is not masked)
        # 断言:x是否等于[0, 1, 10, 40, 4]

        assert_(eq(x, [0, 1, 10, 40, 4]))

    def test_testMaPut(self):
        # Test of put for masked arrays
        # 从self.d中解包变量(x, y, a10, m1, m2, xm, ym, z, zm, xf, s)
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        # 创建一个掩码列表m
        m = [1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
        # 找到掩码列表m中非零元素的索引
        i = np.nonzero(m)[0]
        # 使用put函数将zm放入ym的指定索引位置
        put(ym, i, zm)
        # 断言:从ym中取出指定索引位置的值与zm相等
        assert_(all(take(ym, i, axis=0) == zm))

    def test_testMinMax2(self):
        # Test of minimum, maximum.
        # 断言:对于输入的两个数组,返回元素级的最小值
        assert_(eq(minimum([1, 2, 3], [4, 0, 9]), [1, 0, 3]))
        # 断言:对于输入的两个数组,返回元素级的最大值
        assert_(eq(maximum([1, 2, 3], [4, 0, 9]), [4, 2, 9]))
        # 创建数组x和y,分别为0到4和-2到2的范围
        x = arange(5)
        y = arange(5) - 2
        # 将x的第3个元素屏蔽
        x[3] = masked
        # 将y的第一个元素屏蔽
        y[0] = masked
        # 断言:对x和y中每对元素,返回小于的元素
        assert_(eq(minimum(x, y), where(less(x, y), x, y)))
        # 断言:对x和y中每对元素,返回大于的元素
        assert_(eq(maximum(x, y), where(greater(x, y), x, y)))
        # 断言:返回数组x中的最小值
        assert_(minimum.reduce(x) == 0)
        # 断言:返回数组x中的最大值
        assert_(maximum.reduce(x) == 4)

    def test_testTakeTransposeInnerOuter(self):
        # Test of take, transpose, inner, outer products
        # 创建一个包含0到23的数组x和y
        x = arange(24)
        y = np.arange(24)
        # 将x的第5到第6个元素屏蔽,并将其重塑为2x3x4的数组
        x[5:6] = masked
        x = x.reshape(2, 3, 4)
        # 将y重塑为与x相同的2x3x4的数组
        y = y.reshape(2, 3, 4)
        # 断言:通过维度重新排列,确保x和y的内部结构相同
        assert_(eq(np.transpose(y, (2, 0, 1)), transpose(x, (2, 0, 1))))
        # 断言:使用指定索引从数组中获取元素,并确保x和y的输出相同
        assert_(eq(np.take(y, (2, 0, 1), 1), take(x, (2, 0, 1), 1)))
        # 断言:返回填充为0的x和y的内积
        assert_(eq(np.inner(filled(x, 0), filled(y, 0)),
                   inner(x, y)))
        # 断言:返回填充为0的x和y的外积
        assert_(eq(np.outer(filled(x, 0), filled(y, 0)),
                   outer(x, y)))
        # 创建一个对象数组y,并将其第2个元素屏蔽
        y = array(['abc', 1, 'def', 2, 3], object)
        y[2] = masked
        # 使用指定索引从y中获取元素形成一个新数组t
        t = take(y, [0, 3, 4])
        # 断言:确保数组t的第一个元素为'abc'
        assert_(t[0] == 'abc')
        # 断言:确保数组t的第二个元素为2
        assert_(t[1] == 2)
        # 断言:确保数组t的第三个元素为3
        assert_(t[2] == 3)
    def test_testInplace(self):
        # 测试原地操作和丰富比较
        y = arange(10)  # 创建一个包含0到9的数组y

        x = arange(10)  # 创建一个包含0到9的数组x
        xm = arange(10)  # 创建一个包含0到9的数组xm
        xm[2] = masked  # 将xm的索引为2的位置设为masked(掩码值)
        x += 1  # 将数组x中的每个元素都加1
        assert_(eq(x, y + 1))  # 断言x与y加1后的结果相等
        xm += 1  # 将数组xm中的每个元素都加1
        assert_(eq(x, y + 1))  # 断言xm与y加1后的结果相等

        x = arange(10)  # 创建一个包含0到9的数组x
        xm = arange(10)  # 创建一个包含0到9的数组xm
        xm[2] = masked  # 将xm的索引为2的位置设为masked(掩码值)
        x -= 1  # 将数组x中的每个元素都减1
        assert_(eq(x, y - 1))  # 断言x与y减1后的结果相等
        xm -= 1  # 将数组xm中的每个元素都减1
        assert_(eq(xm, y - 1))  # 断言xm与y减1后的结果相等

        x = arange(10) * 1.0  # 创建一个包含0.0到9.0的浮点数组x
        xm = arange(10) * 1.0  # 创建一个包含0.0到9.0的浮点数组xm
        xm[2] = masked  # 将xm的索引为2的位置设为masked(掩码值)
        x *= 2.0  # 将数组x中的每个元素都乘以2.0
        assert_(eq(x, y * 2))  # 断言x与y乘以2后的结果相等
        xm *= 2.0  # 将数组xm中的每个元素都乘以2.0
        assert_(eq(xm, y * 2))  # 断言xm与y乘以2后的结果相等

        x = arange(10) * 2  # 创建一个包含0到18(步长为2)的数组x
        xm = arange(10)  # 创建一个包含0到9的数组xm
        xm[2] = masked  # 将xm的索引为2的位置设为masked(掩码值)
        x //= 2  # 将数组x中的每个元素都整除以2
        assert_(eq(x, y))  # 断言x与y整除以2后的结果相等
        xm //= 2  # 将数组xm中的每个元素都整除以2
        assert_(eq(x, y))  # 断言xm与y整除以2后的结果相等

        x = arange(10) * 1.0  # 创建一个包含0.0到9.0的浮点数组x
        xm = arange(10) * 1.0  # 创建一个包含0.0到9.0的浮点数组xm
        xm[2] = masked  # 将xm的索引为2的位置设为masked(掩码值)
        x /= 2.0  # 将数组x中的每个元素都除以2.0
        assert_(eq(x, y / 2.0))  # 断言x与y除以2.0后的结果相等
        xm /= arange(10)  # 将数组xm中的每个元素分别除以相应的索引值
        assert_(eq(xm, ones((10,))))  # 断言xm与一个全1数组相等

        x = arange(10).astype(np.float32)  # 创建一个包含0到9的浮点数组x
        xm = arange(10)  # 创建一个包含0到9的数组xm
        xm[2] = masked  # 将xm的索引为2的位置设为masked(掩码值)
        x += 1.  # 将数组x中的每个元素都加1.0
        assert_(eq(x, y + 1.))  # 断言x与y加1.0后的结果相等
    def test_testAverage2(self):
        # 定义测试函数 test_testAverage2
        # 测试 average 函数的不同用例

        # 定义权重和数组
        w1 = [0, 1, 1, 1, 1, 0]
        w2 = [[0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 0, 1]]
        x = arange(6)

        # 断言:验证在指定轴上求平均值,预期结果为 2.5
        assert_(allclose(average(x, axis=0), 2.5))
        
        # 断言:验证在指定轴上使用权重求平均值,预期结果为 2.5
        assert_(allclose(average(x, axis=0, weights=w1), 2.5))
        
        # 定义二维数组 y
        y = array([arange(6), 2.0 * arange(6)])

        # 断言:验证在全局求平均值,预期结果为 (0+1+2+3+4+5) * 3 / 12 = 7.5
        assert_(allclose(average(y, None), np.add.reduce(np.arange(6)) * 3. / 12.))
        
        # 断言:验证在指定轴上求平均值,预期结果为 [0*3/2, 1*3/2, ..., 5*3/2]
        assert_(allclose(average(y, axis=0), np.arange(6) * 3. / 2.))
        
        # 断言:验证在指定轴上求平均值,预期结果为 [平均(x, axis=0), 平均(x, axis=0)*2.0]
        assert_(allclose(average(y, axis=1), [average(x, axis=0), average(x, axis=0)*2.0]))
        
        # 断言:验证在全局使用权重求平均值,预期结果为 20 / 6.0
        assert_(allclose(average(y, None, weights=w2), 20. / 6.))
        
        # 断言:验证在指定轴上使用权重求平均值,预期结果为 [0, 1, 2, 3, 4, 10]
        assert_(allclose(average(y, axis=0, weights=w2), [0., 1., 2., 3., 4., 10.]))
        
        # 以下几个断言均为重复验证,省略重复注释
        m1 = zeros(6)
        m2 = [0, 0, 1, 1, 0, 0]
        m3 = [[0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0]]
        m4 = ones(6)
        m5 = [0, 1, 1, 1, 1, 1]
        assert_(allclose(average(masked_array(x, m1), axis=0), 2.5))
        assert_(allclose(average(masked_array(x, m2), axis=0), 2.5))
        assert_(average(masked_array(x, m4), axis=0) is masked)
        assert_equal(average(masked_array(x, m5), axis=0), 0.0)
        assert_equal(count(average(masked_array(x, m4), axis=0)), 0)
        
        z = masked_array(y, m3)
        assert_(allclose(average(z, None), 20. / 6.))
        assert_(allclose(average(z, axis=0), [0., 1., 99., 99., 4.0, 7.5]))
        assert_(allclose(average(z, axis=1), [2.5, 5.0]))
        assert_(allclose(average(z, axis=0, weights=w2), [0., 1., 99., 99., 4.0, 10.0]))

        a = arange(6)
        b = arange(6) * 3
        r1, w1 = average([[a, b], [b, a]], axis=1, returned=True)
        assert_equal(shape(r1), shape(w1))
        assert_equal(r1.shape, w1.shape)
        r2, w2 = average(ones((2, 2, 3)), axis=0, weights=[3, 1], returned=True)
        assert_equal(shape(w2), shape(r2))
        r2, w2 = average(ones((2, 2, 3)), returned=True)
        assert_equal(shape(w2), shape(r2))
        r2, w2 = average(ones((2, 2, 3)), weights=ones((2, 2, 3)), returned=True)
        assert_(shape(w2) == shape(r2))

        a2d = array([[1, 2], [0, 4]], float)
        a2dm = masked_array(a2d, [[0, 0], [1, 0]])
        a2da = average(a2d, axis=0)
        assert_(eq(a2da, [0.5, 3.0]))
        a2dma = average(a2dm, axis=0)
        assert_(eq(a2dma, [1.0, 3.0]))
        a2dma = average(a2dm, axis=None)
        assert_(eq(a2dma, 7. / 3.))
        a2dma = average(a2dm, axis=1)
        assert_(eq(a2dma, [1.5, 4.0]))
    # 测试将数值转换为数组,并验证转换后的类型是否正确
    def test_testToPython(self):
        # 验证将整数转换为数组后,类型为整数
        assert_equal(1, int(array(1)))
        # 验证将整数转换为浮点数数组后,类型为浮点数
        assert_equal(1.0, float(array(1)))
        # 验证将多维整数数组转换为整数后,类型为整数
        assert_equal(1, int(array([[[1]]])))
        # 验证将二维整数数组转换为浮点数后,类型为浮点数
        assert_equal(1.0, float(array([[1]]))))
        # 验证传递非法参数时是否引发TypeError异常
        assert_raises(TypeError, float, array([1, 1]))
        # 验证传递非法值时是否引发ValueError异常
        assert_raises(ValueError, bool, array([0, 1]))
        # 验证传递带掩码的数组时是否引发ValueError异常
        assert_raises(ValueError, bool, array([0, 0], mask=[0, 1]))

    # 测试标量运算
    def test_testScalarArithmetic(self):
        xm = array(0, mask=1)
        #TODO FIXME: 在r8247中找出以下内容为何引发警告
        # 使用特定的错误状态处理,忽略除以零的警告
        with np.errstate(divide='ignore'):
            assert_((1 / array(0)).mask)
        # 验证在标量加法中是否生成了正确的掩码
        assert_((1 + xm).mask)
        # 验证在标量取反操作中是否生成了正确的掩码
        assert_((-xm).mask)
        # 再次验证在标量取反操作中是否生成了正确的掩码
        assert_((-xm).mask)
        # 验证在取两个掩码的最大值时是否生成了正确的掩码
        assert_(maximum(xm, xm).mask)
        # 验证在取两个掩码的最小值时是否生成了正确的掩码
        assert_(minimum(xm, xm).mask)
        # 验证填充后的数据类型是否与原始数据类型相同
        assert_(xm.filled().dtype is xm._data.dtype)
        # 验证未掩码数组与其数据的相等性
        x = array(0, mask=0)
        assert_(x.filled() == x._data)
        # 验证掩码数组转换为字符串是否与预期的打印选项相等
        assert_equal(str(xm), str(masked_print_option))

    # 测试数组方法
    def test_testArrayMethods(self):
        a = array([1, 3, 2])
        # 验证任意值是否与原始数据的任意值相等
        assert_(eq(a.any(), a._data.any()))
        # 验证所有值是否与原始数据的所有值相等
        assert_(eq(a.all(), a._data.all()))
        # 验证最大值的索引是否与原始数据的最大值索引相等
        assert_(eq(a.argmax(), a._data.argmax()))
        # 验证最小值的索引是否与原始数据的最小值索引相等
        assert_(eq(a.argmin(), a._data.argmin()))
        # 验证选择操作的结果是否与原始数据的选择操作结果相等
        assert_(eq(a.choose(0, 1, 2, 3, 4),
                           a._data.choose(0, 1, 2, 3, 4)))
        # 验证压缩操作的结果是否与原始数据的压缩操作结果相等
        assert_(eq(a.compress([1, 0, 1]), a._data.compress([1, 0, 1])))
        # 验证共轭操作的结果是否与原始数据的共轭操作结果相等
        assert_(eq(a.conj(), a._data.conj()))
        # 验证共轭操作的结果是否与原始数据的共轭操作结果相等
        assert_(eq(a.conjugate(), a._data.conjugate()))
        # 验证对角线元素的结果是否与原始数据的对角线元素结果相等
        m = array([[1, 2], [3, 4]])
        assert_(eq(m.diagonal(), m._data.diagonal()))
        # 验证数组求和的结果是否与原始数据的求和结果相等
        assert_(eq(a.sum(), a._data.sum()))
        # 验证取数组元素的结果是否与原始数据的取元素结果相等
        assert_(eq(a.take([1, 2]), a._data.take([1, 2])))
        # 验证数组转置的结果是否与原始数据的转置结果相等
        assert_(eq(m.transpose(), m._data.transpose()))

    # 测试数组属性
    def test_testArrayAttributes(self):
        a = array([1, 3, 2])
        # 验证数组的维度是否为1
        assert_equal(a.ndim, 1)

    # 测试API
    def test_testAPI(self):
        # 验证不在MaskedArray中且不以下划线开头的所有方法是否都在ndarray中
        assert_(not [m for m in dir(np.ndarray)
                     if m not in dir(MaskedArray) and
                     not m.startswith('_')])

    # 测试单个元素下标
    def test_testSingleElementSubscript(self):
        a = array([1, 3, 2])
        b = array([1, 3, 2], mask=[1, 0, 1])
        # 验证单个元素下标的形状是否为空元组
        assert_equal(a[0].shape, ())
        # 验证带掩码的数组单个元素下标的形状是否为空元组
        assert_equal(b[0].shape, ())
        # 验证带掩码的数组第二个元素下标的形状是否为单元素元组
        assert_equal(b[1].shape, ())

    # 测试条件赋值
    def test_assignment_by_condition(self):
        # 测试gh-18951
        a = array([1, 2, 3, 4], mask=[1, 0, 1, 0])
        # 创建条件,选择满足条件的元素进行赋值
        c = a >= 3
        a[c] = 5
        # 验证条件赋值后的特定索引是否被遮蔽
        assert_(a[2] is masked)

    # 测试条件赋值2
    def test_assignment_by_condition_2(self):
        # gh-19721
        a = masked_array([0, 1], mask=[False, False])
        b = masked_array([0, 1], mask=[True, True])
        # 创建条件,选择满足条件的元素进行赋值
        mask = a < 1
        b[mask] = a[mask]
        expected_mask = [False, True]
        # 验证条件赋值后的掩码是否与预期相符
        assert_equal(b.mask, expected_mask)
class TestUfuncs:
    def setup_method(self):
        # 设置测试方法的初始化数据
        self.d = (array([1.0, 0, -1, pi / 2] * 2, mask=[0, 1] + [0] * 6),
                  array([1.0, 0, -1, pi / 2] * 2, mask=[1, 0] + [0] * 6),)

    def test_testUfuncRegression(self):
        # 定义无效忽略函数列表
        f_invalid_ignore = [
            'sqrt', 'arctanh', 'arcsin', 'arccos',
            'arccosh', 'arctanh', 'log', 'log10', 'divide',
            'true_divide', 'floor_divide', 'remainder', 'fmod']
        # 遍历每个函数并进行测试
        for f in ['sqrt', 'log', 'log10', 'exp', 'conjugate',
                  'sin', 'cos', 'tan',
                  'arcsin', 'arccos', 'arctan',
                  'sinh', 'cosh', 'tanh',
                  'arcsinh',
                  'arccosh',
                  'arctanh',
                  'absolute', 'fabs', 'negative',
                  'floor', 'ceil',
                  '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:
                # 尝试从umath模块获取函数
                uf = getattr(umath, f)
            except AttributeError:
                # 如果umath模块中不存在,则从fromnumeric模块获取
                uf = getattr(fromnumeric, f)
            # 从np.ma模块获取函数
            mf = getattr(np.ma, f)
            # 准备参数,使用uf函数的输入数量切片数据d
            args = self.d[:uf.nin]
            # 设置numpy错误状态
            with np.errstate():
                if f in f_invalid_ignore:
                    np.seterr(invalid='ignore')
                if f in ['arctanh', 'log', 'log10']:
                    np.seterr(divide='ignore')
                # 调用uf函数和mf函数,得到结果
                ur = uf(*args)
                mr = mf(*args)
            # 断言ur的填充0后与mr的填充0后相等,使用函数名作为描述信息
            assert_(eq(ur.filled(0), mr.filled(0), f))
            # 断言ur的掩码与mr的掩码相等
            assert_(eqmask(ur.mask, mr.mask))

    def test_reduce(self):
        # 获取数组self.d的第一个元素
        a = self.d[0]
        # 断言a在轴0上不全为真
        assert_(not alltrue(a, axis=0))
        # 断言a在轴0上至少有一个为真
        assert_(sometrue(a, axis=0))
        # 断言a的前三个元素在轴0上的和为0
        assert_equal(sum(a[:3], axis=0), 0)
        # 断言a在轴0上的乘积为0
        assert_equal(product(a, axis=0), 0)

    def test_minmax(self):
        # 创建一个3x4的数组
        a = arange(1, 13).reshape(3, 4)
        # 使用条件掩码创建一个数组amask
        amask = masked_where(a < 5, a)
        # 断言amask的最大值与a的最大值相等
        assert_equal(amask.max(), a.max())
        # 断言amask的最小值为5
        assert_equal(amask.min(), 5)
        # 断言amask在轴0上的最大值与a在轴0上的最大值全部相等
        assert_((amask.max(0) == a.max(0)).all())
        # 断言amask在轴0上的最小值与[5, 6, 7, 8]全部相等
        assert_((amask.min(0) == [5, 6, 7, 8]).all())
        # 断言amask在轴1上的第一个元素的最大值具有掩码
        assert_(amask.max(1)[0].mask)
        # 断言amask在轴1上的第一个元素的最小值具有掩码
        assert_(amask.min(1)[0].mask)

    def test_nonzero(self):
        # 遍历不同类型的数据类型
        for t in "?bhilqpBHILQPfdgFDGO":
            # 创建一个数组x,包含数据和掩码
            x = array([1, 0, 2, 0], mask=[0, 0, 1, 1])
            # 断言x的非零元素索引为[0]
            assert_(eq(nonzero(x), [0]))
    # 设置测试方法的初始化,准备测试数据
    def setup_method(self):
        # 创建包含浮点数的 NumPy 数组 x
        x = np.array([8.375, 7.545, 8.828, 8.5, 1.757, 5.928,
                      8.43, 7.78, 9.865, 5.878, 8.979, 4.732,
                      3.012, 6.022, 5.095, 3.116, 5.238, 3.957,
                      6.04, 9.63, 7.712, 3.382, 4.489, 6.479,
                      7.189, 9.645, 5.395, 4.961, 9.894, 2.893,
                      7.357, 9.828, 6.272, 3.758, 6.693, 0.993])
        # 将 x 重塑为 6x6 的数组 X
        X = x.reshape(6, 6)
        # 将 x 重塑为 3x2x2x3 的数组 XX
        XX = x.reshape(3, 2, 2, 3)

        # 创建包含 0 和 1 的 NumPy 数组 m
        m = np.array([0, 1, 0, 1, 0, 0,
                      1, 0, 1, 1, 0, 1,
                      0, 0, 0, 1, 0, 1,
                      0, 0, 0, 1, 1, 1,
                      1, 0, 0, 1, 0, 0,
                      0, 0, 1, 0, 1, 0])
        # 使用 x 和 m 创建掩码数组 mx
        mx = array(data=x, mask=m)
        # 使用 X 和 m 重塑的形状创建掩码数组 mX
        mX = array(data=X, mask=m.reshape(X.shape))
        # 使用 XX 和 m 重塑的形状创建掩码数组 mXX
        mXX = array(data=XX, mask=m.reshape(XX.shape))

        # 将所有数据存储在 self.d 中
        self.d = (x, X, XX, m, mx, mX, mXX)

    # 测试计算对角线元素和的方法
    def test_trace(self):
        # 从 self.d 中解包所需的数据
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 计算 mX 的对角线元素
        mXdiag = mX.diagonal()
        # 断言 mX 的迹等于其对角线元素去除掩码后的和
        assert_equal(mX.trace(), mX.diagonal().compressed().sum())
        # 断言 mX 的迹等于 X 的迹减去按位乘积结果的和
        assert_(eq(mX.trace(),
                           X.trace() - sum(mXdiag.mask * X.diagonal(),
                                           axis=0)))

    # 测试剪裁方法
    def test_clip(self):
        # 从 self.d 中解包所需的数据
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 对 mx 应用剪裁操作,剪裁范围为 [2, 8]
        clipped = mx.clip(2, 8)
        # 断言剪裁后的掩码与 mx 的掩码相等
        assert_(eq(clipped.mask, mx.mask))
        # 断言剪裁后的数据与 x 的剪裁结果相等
        assert_(eq(clipped._data, x.clip(2, 8)))
        # 断言剪裁后的数据与 mx 的剪裁结果相等
        assert_(eq(clipped._data, mx._data.clip(2, 8)))

    # 测试峰值到峰值方法
    def test_ptp(self):
        # 从 self.d 中解包所需的数据
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 计算 mx 的峰值到峰值
        assert_equal(mx.ptp(), np.ptp(mx.compressed()))
        # 创建一个全零的行和列数组,用于存储结果
        rows = np.zeros(n, np.float64)
        cols = np.zeros(m, np.float64)
        # 计算 mX 每列的峰值到峰值,并存储在 cols 数组中
        for k in range(m):
            cols[k] = np.ptp(mX[:, k].compressed())
        # 计算 mX 每行的峰值到峰值,并存储在 rows 数组中
        for k in range(n):
            rows[k] = np.ptp(mX[k].compressed())
        # 断言 mX 沿指定轴的峰值到峰值等于预期结果
        assert_(eq(mX.ptp(0), cols))
        assert_(eq(mX.ptp(1), rows))

    # 测试交换轴方法
    def test_swapaxes(self):
        # 从 self.d 中解包所需的数据
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 对 mX 执行轴交换操作
        mXswapped = mX.swapaxes(0, 1)
        # 断言交换后的最后一个轴与原始数据的最后一个轴相等
        assert_(eq(mXswapped[-1], mX[:, -1]))
        # 对 mXX 执行轴交换操作,并断言结果形状符合预期
        mXXswapped = mXX.swapaxes(0, 2)
        assert_equal(mXXswapped.shape, (2, 2, 3, 3))

    # 测试累积乘积方法
    def test_cumprod(self):
        # 从 self.d 中解包所需的数据
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 对 mX 执行沿第一个轴的累积乘积操作
        mXcp = mX.cumprod(0)
        # 断言累积乘积结果的数据部分与填充后的 mX 结果相等
        assert_(eq(mXcp._data, mX.filled(1).cumprod(0)))
        # 对 mX 执行沿第二个轴的累积乘积操作
        mXcp = mX.cumprod(1)
        # 断言累积乘积结果的数据部分与填充后的 mX 结果相等
        assert_(eq(mXcp._data, mX.filled(1).cumprod(1)))

    # 测试累积求和方法
    def test_cumsum(self):
        # 从 self.d 中解包所需的数据
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 对 mX 执行沿第一个轴的累积求和操作
        mXcp = mX.cumsum(0)
        # 断言累积求和结果的数据部分与填充后的 mX 结果相等
        assert_(eq(mXcp._data, mX.filled(0).cumsum(0)))
        # 对 mX 执行沿第二个轴的累积求和操作
        mXcp = mX.cumsum(1)
        # 断言累积求和结果的数据部分与填充后的 mX 结果相等
        assert_(eq(mXcp._data, mX.filled(0).cumsum(1)))
    # 定义一个测试函数,用于验证变量标准差的计算是否正确
    def test_varstd(self):
        # 从数据集 self.d 中解包变量
        (x, X, XX, m, mx, mX, mXX,) = self.d
        # 断言检查:比较 mX 沿着所有轴的方差和经过压缩后的 mX 的方差是否相等
        assert_(eq(mX.var(axis=None), mX.compressed().var()))
        # 断言检查:比较 mX 沿着所有轴的标准差和经过压缩后的 mX 的标准差是否相等
        assert_(eq(mX.std(axis=None), mX.compressed().std()))
        # 断言检查:比较 mXX 沿着第 3 个轴计算方差后的形状和 XX 沿着第 3 个轴计算方差后的形状是否相等
        assert_(eq(mXX.var(axis=3).shape, XX.var(axis=3).shape))
        # 断言检查:比较 mX 沿着所有轴计算方差的形状和 X 沿着所有轴计算方差的形状是否相等
        assert_(eq(mX.var().shape, X.var().shape))
        # 解包 mX 沿着第 0 轴和第 1 轴的方差
        (mXvar0, mXvar1) = (mX.var(axis=0), mX.var(axis=1))
        # 循环检查每个索引 k
        for k in range(6):
            # 断言检查:比较 mXvar1[k] 和经过压缩后的 mX[k] 的方差是否相等
            assert_(eq(mXvar1[k], mX[k].compressed().var()))
            # 断言检查:比较 mXvar0[k] 和经过压缩后的 mX[:, k] 的方差是否相等
            assert_(eq(mXvar0[k], mX[:, k].compressed().var()))
            # 断言检查:比较 mXvar0[k] 的平方根和经过压缩后的 mX[:, k] 的标准差是否相等
            assert_(eq(np.sqrt(mXvar0[k]),
                               mX[:, k].compressed().std()))
# 定义一个函数,用于比较两个掩码(mask)是否相等
def eqmask(m1, m2):
    # 如果 m1 是 nomask,则判断 m2 是否也是 nomask,若是则返回 True
    if m1 is nomask:
        return m2 is nomask
    # 如果 m2 是 nomask,则判断 m1 是否也是 nomask,若是则返回 True
    if m2 is nomask:
        return m1 is nomask
    # 如果 m1 和 m2 都不是 nomask,则比较它们的所有元素是否相等,返回比较结果
    return (m1 == m2).all()

.\numpy\numpy\ma\tests\test_regression.py

import numpy as np  # 导入 NumPy 库,通常用于数值计算
from numpy.testing import (  # 从 NumPy 的 testing 模块导入以下函数和类
    assert_, assert_array_equal, assert_allclose, suppress_warnings
    )


class TestRegression:
    def test_masked_array_create(self):
        # Ticket #17
        # 创建一个掩码数组 x,其中部分元素被掩盖(masked)
        x = np.ma.masked_array([0, 1, 2, 3, 0, 4, 5, 6],
                               mask=[0, 0, 0, 1, 1, 1, 0, 0])
        assert_array_equal(np.ma.nonzero(x), [[1, 2, 6, 7]])  # 验证非零元素的索引

    def test_masked_array(self):
        # Ticket #61
        np.ma.array(1, mask=[1])  # 创建一个掩码数组,其中唯一元素被掩盖

    def test_mem_masked_where(self):
        # Ticket #62
        from numpy.ma import masked_where, MaskType  # 从 NumPy 的 ma 模块导入函数和类
        a = np.zeros((1, 1))  # 创建一个形状为 (1, 1) 的全零数组 a
        b = np.zeros(a.shape, MaskType)  # 使用 MaskType 类型创建与 a 相同形状的全零数组 b
        c = masked_where(b, a)  # 根据 b 的掩码创建一个掩码数组 c
        a-c  # 数组 a 减去数组 c 的结果

    def test_masked_array_multiply(self):
        # Ticket #254
        a = np.ma.zeros((4, 1))  # 创建一个形状为 (4, 1) 的全零掩码数组 a
        a[2, 0] = np.ma.masked  # 将 a 中第 (2, 0) 元素设为掩盖状态
        b = np.zeros((4, 2))  # 创建一个形状为 (4, 2) 的全零数组 b
        a*b  # 掩码数组 a 与数组 b 的乘积
        b*a  # 数组 b 与掩码数组 a 的乘积

    def test_masked_array_repeat(self):
        # Ticket #271
        np.ma.array([1], mask=False).repeat(10)  # 创建一个非掩码数组,其中的元素重复十次

    def test_masked_array_repr_unicode(self):
        # Ticket #1256
        repr(np.ma.array("Unicode"))  # 创建一个包含字符串 "Unicode" 的掩码数组的表示形式

    def test_atleast_2d(self):
        # Ticket #1559
        a = np.ma.masked_array([0.0, 1.2, 3.5], mask=[False, True, False])  # 创建一个掩码数组 a
        b = np.atleast_2d(a)  # 将数组 a 至少转换为二维数组 b
        assert_(a.mask.ndim == 1)  # 验证数组 a 的掩码维度为 1
        assert_(b.mask.ndim == 2)  # 验证数组 b 的掩码维度为 2

    def test_set_fill_value_unicode_py3(self):
        # Ticket #2733
        a = np.ma.masked_array(['a', 'b', 'c'], mask=[1, 0, 0])  # 创建一个掩码数组 a,使用字符串和掩码
        a.fill_value = 'X'  # 设置掩码数组 a 的填充值为 'X'
        assert_(a.fill_value == 'X')  # 验证掩码数组 a 的填充值是否为 'X'

    def test_var_sets_maskedarray_scalar(self):
        # Issue gh-2757
        a = np.ma.array(np.arange(5), mask=True)  # 创建一个掩码数组 a,包含五个元素且全部被掩盖
        mout = np.ma.array(-1, dtype=float)  # 创建一个类型为 float 的掩码数组 mout,包含一个元素 -1
        a.var(out=mout)  # 计算数组 a 的方差,并将结果存储在 mout 中
        assert_(mout._data == 0)  # 验证 mout 的数据为 0

    def test_ddof_corrcoef(self):
        # See gh-3336
        x = np.ma.masked_equal([1, 2, 3, 4, 5], 4)  # 创建一个掩码数组 x,其中数值 4 被掩盖
        y = np.array([2, 2.5, 3.1, 3, 5])  # 创建一个普通数组 y
        with suppress_warnings() as sup:  # 忽略警告
            sup.filter(DeprecationWarning, "bias and ddof have no effect")
            r0 = np.ma.corrcoef(x, y, ddof=0)  # 计算 x 和 y 的相关系数,忽略自由度 ddof
            r1 = np.ma.corrcoef(x, y, ddof=1)  # 计算 x 和 y 的相关系数,忽略自由度 ddof
            assert_allclose(r0.data, r1.data)  # 验证 r0 和 r1 的相关系数数据近似相等

    def test_mask_not_backmangled(self):
        # See gh-10314.  Test case taken from gh-3140.
        a = np.ma.MaskedArray([1., 2.], mask=[False, False])  # 创建一个掩码数组 a,包含两个未被掩盖的元素
        assert_(a.mask.shape == (2,))  # 验证数组 a 的掩码形状为 (2,)
        b = np.tile(a, (2, 1))  # 将数组 a 在行方向复制两次,列方向复制一次,形成新数组 b
        assert_(a.mask.shape == (2,))  # 再次验证数组 a 的掩码形状仍为 (2,)
        assert_(b.shape == (2, 2))  # 验证新数组 b 的形状为 (2, 2)
        assert_(b.mask.shape == (2, 2))  # 验证新数组 b 的掩码形状为 (2, 2)

    def test_empty_list_on_structured(self):
        # See gh-12464. Indexing with empty list should give empty result.
        ma = np.ma.MaskedArray([(1, 1.), (2, 2.), (3, 3.)], dtype='i4,f4')  # 创建一个结构化的掩码数组 ma
        assert_array_equal(ma[[]], ma[:0])  # 验证使用空列表进行索引操作得到空结果
    # 定义测试函数 test_masked_array_tobytes_fortran,用于测试 masked array 对象的 tobytes 方法在 Fortran 排序下的行为
    def test_masked_array_tobytes_fortran(self):
        # 创建一个 2x2 的 masked array 对象 ma,包含数字 0 到 3
        ma = np.ma.arange(4).reshape((2,2))
        # 断言使用 Fortran 排序的 ma 对象的字节表示与其转置后再使用 Fortran 排序的结果相等
        assert_array_equal(ma.tobytes(order='F'), ma.T.tobytes())
    
    # 定义测试函数 test_structured_array,用于测试结构化数组的特定情况
    def test_structured_array():
        # 参考 GitHub issue gh-22041
        # 创建一个结构化数组,包含整数 x 和一个元组 (i, j),元组中的值为 void 类型
        np.ma.array((1, (b"", b"")),
                    dtype=[("x", np.int_),
                          ("y", [("i", np.void), ("j", np.void)])])

.\numpy\numpy\ma\tests\test_subclassing.py

# pylint: disable-msg=W0611, W0612, W0511,R0201
"""Tests suite for MaskedArray & subclassing.

:author: Pierre Gerard-Marchant
:contact: pierregm_at_uga_dot_edu
:version: $Id: test_subclassing.py 3473 2007-10-29 15:18:13Z jarrod.millman $

"""
# 导入 NumPy 库
import numpy as np
# 导入 NumPy 数组操作的混合类
from numpy.lib.mixins import NDArrayOperatorsMixin
# 导入 NumPy 测试工具
from numpy.testing import assert_, assert_raises
# 导入 NumPy 掩码数组相关测试工具
from numpy.ma.testutils import assert_equal
# 导入 NumPy 掩码数组核心功能
from numpy.ma.core import (
    array, arange, masked, MaskedArray, masked_array, log, add, hypot,
    divide, asarray, asanyarray, nomask
    )

# 定义一个自定义断言函数,用于比较字符串开头
def assert_startswith(a, b):
    # 比 assert_(a.startswith(b)) 提供更好的错误信息
    assert_equal(a[:len(b)], b)

# 定义一个 NumPy 的子类 SubArray,存储在字典 `info` 中的一些元数据
class SubArray(np.ndarray):
    def __new__(cls,arr,info={}):
        x = np.asanyarray(arr).view(cls)
        x.info = info.copy()
        return x

    def __array_finalize__(self, obj):
        super().__array_finalize__(obj)
        self.info = getattr(obj, 'info', {}).copy()
        return

    def __add__(self, other):
        result = super().__add__(other)
        result.info['added'] = result.info.get('added', 0) + 1
        return result

    def __iadd__(self, other):
        result = super().__iadd__(other)
        result.info['iadded'] = result.info.get('iadded', 0) + 1
        return result

# 创建一个别名 subarray 指向 SubArray 类
subarray = SubArray

# 定义一个纯粹的 MaskedArray 子类 SubMaskedArray,保留了一些子类信息
class SubMaskedArray(MaskedArray):
    def __new__(cls, info=None, **kwargs):
        obj = super().__new__(cls, **kwargs)
        obj._optinfo['info'] = info
        return obj

# 定义一个同时继承 SubArray 和 MaskedArray 的 MSubArray 子类
class MSubArray(SubArray, MaskedArray):

    def __new__(cls, data, info={}, mask=nomask):
        subarr = SubArray(data, info)
        _data = MaskedArray.__new__(cls, data=subarr, mask=mask)
        _data.info = subarr.info
        return _data

    @property
    def _series(self):
        _view = self.view(MaskedArray)
        _view._sharedmask = False
        return _view

# 创建一个别名 msubarray 指向 MSubArray 类
msubarray = MSubArray

# 定义 CSAIterator 类,用作扁平化迭代器对象
class CSAIterator:
    """
    Flat iterator object that uses its own setter/getter
    (works around ndarray.flat not propagating subclass setters/getters
    see https://github.com/numpy/numpy/issues/4564)
    roughly following MaskedIterator
    """
    def __init__(self, a):
        self._original = a
        self._dataiter = a.view(np.ndarray).flat

    def __iter__(self):
        return self

# 代码块结束
    # 定义特殊方法 __getitem__,用于实现索引操作
    def __getitem__(self, indx):
        # 从 _dataiter 中获取索引为 indx 的元素
        out = self._dataiter.__getitem__(indx)
        # 如果获取的元素不是 ndarray 类型,则将其转换为 ndarray 类型
        if not isinstance(out, np.ndarray):
            out = out.__array__()
        # 将 ndarray 类型的数据视图转换为原始类型 self._original
        out = out.view(type(self._original))
        # 返回转换后的数据
        return out

    # 定义特殊方法 __setitem__,用于实现设置索引操作
    def __setitem__(self, index, value):
        # 将 value 参数传递给 self._original._validate_input 方法进行验证和处理,然后设置到 self._dataiter 的 index 索引位置
        self._dataiter[index] = self._original._validate_input(value)

    # 定义特殊方法 __next__,用于实现迭代器的下一个元素获取操作
    def __next__(self):
        # 获取下一个迭代器 _dataiter 的元素,并将其转换为 ndarray 类型,再将其视图转换为原始类型 self._original
        return next(self._dataiter).__array__().view(type(self._original))
class TestSubclassing:
    # Test suite for masked subclasses of ndarray.

    def setup_method(self):
        # 设置测试方法的初始数据
        x = np.arange(5, dtype='float')
        # 创建一个包含浮点数的 ndarray
        mx = msubarray(x, mask=[0, 1, 0, 0, 0])
        # 创建一个带有掩码的子类数组
        self.data = (x, mx)

    def test_data_subclassing(self):
        # Tests whether the subclass is kept.
        # 测试子类是否被保留
        x = np.arange(5)
        # 创建一个普通的 ndarray
        m = [0, 0, 1, 0, 0]
        xsub = SubArray(x)
        # 使用 SubArray 创建一个子类数组
        xmsub = masked_array(xsub, mask=m)
        # 使用掩码创建一个 MaskedArray
        assert_(isinstance(xmsub, MaskedArray))
        # 断言 xmsub 是 MaskedArray 的实例
        assert_equal(xmsub._data, xsub)
        # 断言 xmsub 的 _data 属性与 xsub 相同
        assert_(isinstance(xmsub._data, SubArray))
        # 断言 xmsub 的 _data 属性是 SubArray 的实例
    # 测试 MaskedArray 的子类化
    def test_maskedarray_subclassing(self):
        # 获取测试数据中的 x 和 mx
        (x, mx) = self.data
        # 断言 mx._data 是 subarray 类的实例
        assert_(isinstance(mx._data, subarray))

    # 测试掩码一元操作
    def test_masked_unary_operations(self):
        # 获取测试数据中的 x 和 mx
        (x, mx) = self.data
        # 在忽略除法警告的上下文中
        with np.errstate(divide='ignore'):
            # 断言 log(mx) 是 msubarray 类的实例
            assert_(isinstance(log(mx), msubarray))
            # 断言 log(x) 等于 np.log(x)
            assert_equal(log(x), np.log(x))

    # 测试掩码二元操作
    def test_masked_binary_operations(self):
        # 获取测试数据中的 x 和 mx
        (x, mx) = self.data
        # 结果应该是 msubarray 类的实例
        assert_(isinstance(add(mx, mx), msubarray))
        assert_(isinstance(add(mx, x), msubarray))
        # 断言加法操作的结果正确
        assert_equal(add(mx, x), mx+x)
        assert_(isinstance(add(mx, mx)._data, subarray))
        assert_(isinstance(add.outer(mx, mx), msubarray))
        assert_(isinstance(hypot(mx, mx), msubarray))
        assert_(isinstance(hypot(mx, x), msubarray))

    # 测试 domained_masked_binary_operation
    def test_masked_binary_operations2(self):
        # 获取测试数据中的 x 和 mx
        (x, mx) = self.data
        # 创建 xmx 对象,使用 mx 的数据和掩码
        xmx = masked_array(mx.data.__array__(), mask=mx.mask)
        assert_(isinstance(divide(mx, mx), msubarray))
        assert_(isinstance(divide(mx, x), msubarray))
        # 断言 divide(mx, mx) 等于 divide(xmx, xmx)
        assert_equal(divide(mx, mx), divide(xmx, xmx))

    # 测试属性传播
    def test_attributepropagation(self):
        # 创建带有掩码的数组 x
        x = array(arange(5), mask=[0]+[1]*4)
        # 创建 masked_array my 和 msubarray ym
        my = masked_array(subarray(x))
        ym = msubarray(x)
        #
        z = (my+1)
        # 断言 z 是 MaskedArray 类的实例,但不是 MSubArray 的实例
        assert_(isinstance(z, MaskedArray))
        assert_(not isinstance(z, MSubArray))
        assert_(isinstance(z._data, SubArray))
        assert_equal(z._data.info, {})
        #
        z = (ym+1)
        # 断言 z 是 MaskedArray 和 MSubArray 的实例
        assert_(isinstance(z, MaskedArray))
        assert_(isinstance(z, MSubArray))
        assert_(isinstance(z._data, SubArray))
        assert_(z._data.info['added'] > 0)
        # 测试数据的原地方法是否被使用 (gh-4617)
        ym += 1
        assert_(isinstance(ym, MaskedArray))
        assert_(isinstance(ym, MSubArray))
        assert_(isinstance(ym._data, SubArray))
        assert_(ym._data.info['iadded'] > 0)
        #
        ym._set_mask([1, 0, 0, 0, 1])
        assert_equal(ym._mask, [1, 0, 0, 0, 1])
        ym._series._set_mask([0, 0, 0, 0, 1])
        assert_equal(ym._mask, [0, 0, 0, 0, 1])
        #
        xsub = subarray(x, info={'name':'x'})
        mxsub = masked_array(xsub)
        # 断言 mxsub 具有 'info' 属性,并且其值等于 xsub 的 'info'
        assert_(hasattr(mxsub, 'info'))
        assert_equal(mxsub.info, xsub.info)
    def test_subclasspreservation(self):
        # 检查使用 masked_array(...,subok=True) 是否能够保留类的类型。
        x = np.arange(5)  # 创建一个长度为5的 NumPy 数组 x
        m = [0, 0, 1, 0, 0]  # 创建一个掩码数组 m
        xinfo = [(i, j) for (i, j) in zip(x, m)]  # 创建一个包含元组的列表 xinfo,元组由 x 和 m 的对应元素组成
        xsub = MSubArray(x, mask=m, info={'xsub':xinfo})  # 创建一个自定义子类 MSubArray 的对象 xsub

        # 使用 subok=False 创建 masked_array 对象 mxsub,并进行断言检查
        mxsub = masked_array(xsub, subok=False)
        assert_(not isinstance(mxsub, MSubArray))  # 断言 mxsub 不是 MSubArray 类的实例
        assert_(isinstance(mxsub, MaskedArray))  # 断言 mxsub 是 MaskedArray 类的实例
        assert_equal(mxsub._mask, m)  # 断言 mxsub 的掩码与 m 相等

        # 使用 asarray(xsub) 创建 mxsub,并进行断言检查
        mxsub = asarray(xsub)
        assert_(not isinstance(mxsub, MSubArray))  # 断言 mxsub 不是 MSubArray 类的实例
        assert_(isinstance(mxsub, MaskedArray))  # 断言 mxsub 是 MaskedArray 类的实例
        assert_equal(mxsub._mask, m)  # 断言 mxsub 的掩码与 m 相等

        # 使用 subok=True 创建 masked_array 对象 mxsub,并进行断言检查
        mxsub = masked_array(xsub, subok=True)
        assert_(isinstance(mxsub, MSubArray))  # 断言 mxsub 是 MSubArray 类的实例
        assert_equal(mxsub.info, xsub.info)  # 断言 mxsub 的信息与 xsub 的信息相等
        assert_equal(mxsub._mask, xsub._mask)  # 断言 mxsub 的掩码与 xsub 的掩码相等

        # 使用 asanyarray(xsub) 创建 mxsub,并进行断言检查
        mxsub = asanyarray(xsub)
        assert_(isinstance(mxsub, MSubArray))  # 断言 mxsub 是 MSubArray 类的实例
        assert_equal(mxsub.info, xsub.info)  # 断言 mxsub 的信息与 xsub 的信息相等
        assert_equal(mxsub._mask, m)  # 断言 mxsub 的掩码与 m 相等

    def test_subclass_items(self):
        """测试 getter 和 setter 是否通过基类进行"""
        x = np.arange(5)  # 创建一个长度为5的 NumPy 数组 x
        xcsub = ComplicatedSubArray(x)  # 创建一个复杂子类 ComplicatedSubArray 的对象 xcsub
        mxcsub = masked_array(xcsub, mask=[True, False, True, False, False])  # 使用掩码创建 masked_array 对象 mxcsub

        # getter 应该返回 ComplicatedSubArray,即使是单个项
        # 首先检查我们正确地编写了 ComplicatedSubArray
        assert_(isinstance(xcsub[1], ComplicatedSubArray))  # 断言 xcsub[1] 是 ComplicatedSubArray 类的实例
        assert_(isinstance(xcsub[1,...], ComplicatedSubArray))  # 断言 xcsub[1,...] 是 ComplicatedSubArray 类的实例
        assert_(isinstance(xcsub[1:4], ComplicatedSubArray))  # 断言 xcsub[1:4] 是 ComplicatedSubArray 类的实例

        # 现在它在 MaskedArray 内部传播
        assert_(isinstance(mxcsub[1], ComplicatedSubArray))  # 断言 mxcsub[1] 是 ComplicatedSubArray 类的实例
        assert_(isinstance(mxcsub[1,...].data, ComplicatedSubArray))  # 断言 mxcsub[1,...].data 是 ComplicatedSubArray 类的实例
        assert_(mxcsub[0] is masked)  # 断言 mxcsub[0] 是 masked
        assert_(isinstance(mxcsub[0,...].data, ComplicatedSubArray))  # 断言 mxcsub[0,...].data 是 ComplicatedSubArray 类的实例
        assert_(isinstance(mxcsub[1:4].data, ComplicatedSubArray))  # 断言 mxcsub[1:4].data 是 ComplicatedSubArray 类的实例

        # 对扁平化版本进行同样的测试(通过 MaskedIterator)
        assert_(isinstance(mxcsub.flat[1].data, ComplicatedSubArray))  # 断言 mxcsub.flat[1].data 是 ComplicatedSubArray 类的实例
        assert_(mxcsub.flat[0] is masked)  # 断言 mxcsub.flat[0] 是 masked
        assert_(isinstance(mxcsub.flat[1:4].base, ComplicatedSubArray))  # 断言 mxcsub.flat[1:4].base 是 ComplicatedSubArray 类的实例

        # setter 只能接受 ComplicatedSubArray 类型的输入
        # 首先检查我们正确地编写了 ComplicatedSubArray
        assert_raises(ValueError, xcsub.__setitem__, 1, x[4])  # 断言对 xcsub[1] 设置 x[4] 会引发 ValueError
        # 现在它在 MaskedArray 内部传播
        assert_raises(ValueError, mxcsub.__setitem__, 1, x[4])  # 断言对 mxcsub[1] 设置 x[4] 会引发 ValueError
        assert_raises(ValueError, mxcsub.__setitem__, slice(1, 4), x[1:4])  # 断言对 mxcsub[1:4] 设置 x[1:4] 会引发 ValueError
        mxcsub[1] = xcsub[4]  # 设置 mxcsub[1] 为 xcsub[4]
        mxcsub[1:4] = xcsub[1:4]  # 设置 mxcsub[1:4] 为 xcsub[1:4]

        # 对扁平化版本进行同样的测试(通过 MaskedIterator)
        assert_raises(ValueError, mxcsub.flat.__setitem__, 1, x[4])  # 断言对 mxcsub.flat[1] 设置 x[4] 会引发 ValueError
        assert_raises(ValueError, mxcsub.flat.__setitem__, slice(1, 4), x[1:4])  # 断言对 mxcsub.flat[1:4] 设置 x[1:4] 会引发 ValueError
        mxcsub.flat[1] = xcsub[4]  # 设置 mxcsub.flat[1] 为 xcsub[4]
        mxcsub.flat[1:4] = xcsub[1:4]  # 设置 mxcsub.flat[1:4] 为 xcsub[1:4]
    def test_subclass_nomask_items(self):
        x = np.arange(5)
        xcsub = ComplicatedSubArray(x)  # 创建一个名为xcsub的ComplicatedSubArray对象,使用x作为数据
        mxcsub_nomask = masked_array(xcsub)  # 创建一个名为mxcsub_nomask的masked_array对象,使用xcsub作为数据

        assert_(isinstance(mxcsub_nomask[1,...].data, ComplicatedSubArray))  # 断言mxcsub_nomask的第二个元素数据为ComplicatedSubArray类型
        assert_(isinstance(mxcsub_nomask[0,...].data, ComplicatedSubArray))  # 断言mxcsub_nomask的第一个元素数据为ComplicatedSubArray类型

        assert_(isinstance(mxcsub_nomask[1], ComplicatedSubArray))  # 断言mxcsub_nomask的第二个元素为ComplicatedSubArray类型
        assert_(isinstance(mxcsub_nomask[0], ComplicatedSubArray))  # 断言mxcsub_nomask的第一个元素为ComplicatedSubArray类型

    def test_subclass_repr(self):
        """test that repr uses the name of the subclass
        and 'array' for np.ndarray"""
        x = np.arange(5)
        mx = masked_array(x, mask=[True, False, True, False, False])  # 创建一个名为mx的masked_array对象,使用x作为数据和指定的掩码

        assert_startswith(repr(mx), 'masked_array')  # 断言mx的repr字符串以'masked_array'开头
        xsub = SubArray(x)  # 创建一个名为xsub的SubArray对象,使用x作为数据
        mxsub = masked_array(xsub, mask=[True, False, True, False, False])  # 创建一个名为mxsub的masked_array对象,使用xsub作为数据和指定的掩码
        assert_startswith(repr(mxsub),
            f'masked_{SubArray.__name__}(data=[--, 1, --, 3, 4]')  # 断言mxsub的repr字符串以'masked_SubArray'开头,并包含指定格式的数据表示

    def test_subclass_str(self):
        """test str with subclass that has overridden str, setitem"""
        # first without override
        x = np.arange(5)
        xsub = SubArray(x)  # 创建一个名为xsub的SubArray对象,使用x作为数据
        mxsub = masked_array(xsub, mask=[True, False, True, False, False])  # 创建一个名为mxsub的masked_array对象,使用xsub作为数据和指定的掩码
        assert_equal(str(mxsub), '[-- 1 -- 3 4]')  # 断言mxsub的str字符串为指定格式的字符串表示

        xcsub = ComplicatedSubArray(x)  # 创建一个名为xcsub的ComplicatedSubArray对象,使用x作为数据
        assert_raises(ValueError, xcsub.__setitem__, 0,
                      np.ma.core.masked_print_option)  # 使用xcsub对象尝试调用__setitem__方法,并断言引发ValueError异常
        mxcsub = masked_array(xcsub, mask=[True, False, True, False, False])  # 创建一个名为mxcsub的masked_array对象,使用xcsub作为数据和指定的掩码
        assert_equal(str(mxcsub), 'myprefix [-- 1 -- 3 4] mypostfix')  # 断言mxcsub的str字符串为指定格式的字符串表示

    def test_pure_subclass_info_preservation(self):
        # Test that ufuncs and methods conserve extra information consistently;
        # see gh-7122.
        arr1 = SubMaskedArray('test', data=[1,2,3,4,5,6])  # 创建一个名为arr1的SubMaskedArray对象,使用指定的信息字符串和数据
        arr2 = SubMaskedArray(data=[0,1,2,3,4,5])  # 创建一个名为arr2的SubMaskedArray对象,使用数据作为数据
        diff1 = np.subtract(arr1, arr2)  # 使用np.subtract函数计算arr1和arr2的差异,并赋值给diff1
        assert_('info' in diff1._optinfo)  # 断言diff1的_optinfo字典中包含'info'键
        assert_(diff1._optinfo['info'] == 'test')  # 断言diff1的_optinfo字典中'info'键的值为'test'
        diff2 = arr1 - arr2  # 计算arr1和arr2的差异,并赋值给diff2
        assert_('info' in diff2._optinfo)  # 断言diff2的_optinfo字典中包含'info'键
        assert_(diff2._optinfo['info'] == 'test')  # 断言diff2的_optinfo字典中'info'键的值为'test'
class ArrayNoInheritance:
    """Quantity-like class that does not inherit from ndarray"""
    
    def __init__(self, data, units):
        # Initialize with data and units
        self.magnitude = data  # Store data in the magnitude attribute
        self.units = units  # Store units information
    
    def __getattr__(self, attr):
        # Delegate attribute access to self.magnitude
        return getattr(self.magnitude, attr)


def test_array_no_inheritance():
    # Create a masked array with data [1, 2, 3] and mask [True, False, True]
    data_masked = np.ma.array([1, 2, 3], mask=[True, False, True])
    # Create an instance of ArrayNoInheritance with the masked array and 'meters' units
    data_masked_units = ArrayNoInheritance(data_masked, 'meters')

    # Get the masked representation of the Quantity-like class
    new_array = np.ma.array(data_masked_units)
    assert_equal(data_masked.data, new_array.data)  # Check data equality
    assert_equal(data_masked.mask, new_array.mask)  # Check mask equality
    # Test sharing the mask
    data_masked.mask = [True, False, False]  # Change the mask of data_masked
    assert_equal(data_masked.mask, new_array.mask)  # Assert that new_array's mask also changes
    assert_(new_array.sharedmask)  # Assert that new_array shares its mask

    # Get the masked representation of the Quantity-like class with copy=True
    new_array = np.ma.array(data_masked_units, copy=True)
    assert_equal(data_masked.data, new_array.data)  # Check data equality
    assert_equal(data_masked.mask, new_array.mask)  # Check mask equality
    # Test that the mask is not shared when copy=True
    data_masked.mask = [True, False, True]  # Change the mask of data_masked
    assert_equal([True, False, False], new_array.mask)  # Assert new_array's mask remains unchanged
    assert_(not new_array.sharedmask)  # Assert new_array does not share its mask

    # Get the masked representation of the Quantity-like class with keep_mask=False
    new_array = np.ma.array(data_masked_units, keep_mask=False)
    assert_equal(data_masked.data, new_array.data)  # Check data equality
    # The change did not affect the original mask
    assert_equal(data_masked.mask, [True, False, True])  # Check original mask remains unchanged
    # Test that the mask is False and not shared when keep_mask=False
    assert_(not new_array.mask)  # Assert new_array's mask is False
    assert_(not new_array.sharedmask)  # Assert new_array does not share its mask


class TestClassWrapping:
    # Test suite for classes that wrap MaskedArrays

    def setup_method(self):
        # Setup method to create masked and wrapped arrays
        m = np.ma.masked_array([1, 3, 5], mask=[False, True, False])
        wm = WrappedArray(m)  # Assuming WrappedArray is defined elsewhere
        self.data = (m, wm)  # Store masked and wrapped arrays in self.data

    def test_masked_unary_operations(self):
        # Tests masked_unary_operation
        (m, wm) = self.data  # Unpack self.data into masked array (m) and wrapped array (wm)
        with np.errstate(divide='ignore'):
            assert_(isinstance(np.log(wm), WrappedArray))  # Check if np.log(wm) is instance of WrappedArray
    # 定义测试函数,用于测试掩码二进制操作
    def test_masked_binary_operations(self):
        # 测试 masked_binary_operation 函数
        (m, wm) = self.data
        # 断言结果应为 WrappedArray 类型
        assert_(isinstance(np.add(wm, wm), WrappedArray))
        assert_(isinstance(np.add(m, wm), WrappedArray))
        assert_(isinstance(np.add(wm, m), WrappedArray))
        # add 和 '+' 应调用相同的 ufunc
        assert_equal(np.add(m, wm), m + wm)
        assert_(isinstance(np.hypot(m, wm), WrappedArray))
        assert_(isinstance(np.hypot(wm, m), WrappedArray))
        # 测试包含定义域的二进制操作
        assert_(isinstance(np.divide(wm, m), WrappedArray))
        assert_(isinstance(np.divide(m, wm), WrappedArray))
        assert_equal(np.divide(wm, m) * m, np.divide(m, m) * wm)
        # 测试广播功能
        m2 = np.stack([m, m])
        assert_(isinstance(np.divide(wm, m2), WrappedArray))
        assert_(isinstance(np.divide(m2, wm), WrappedArray))
        assert_equal(np.divide(m2, wm), np.divide(wm, m2))

    # 定义测试函数,用于验证混合类是否具有 slots 属性
    def test_mixins_have_slots(self):
        mixin = NDArrayOperatorsMixin()
        # 应抛出 AttributeError 异常
        assert_raises(AttributeError, mixin.__setattr__, "not_a_real_attr", 1)

        m = np.ma.masked_array([1, 3, 5], mask=[False, True, False])
        wm = WrappedArray(m)
        # 应抛出 AttributeError 异常
        assert_raises(AttributeError, wm.__setattr__, "not_an_attr", 2)

.\numpy\numpy\ma\tests\__init__.py

# 导入所需的模块:os 用于操作文件系统,re 用于正则表达式处理
import os
import re

# 定义一个函数,参数为目录路径
def find_files(directory):
    # 初始化一个空列表,用于存储符合条件的文件名
    file_list = []
    # 遍历指定目录下的所有文件和文件夹
    for root, dirs, files in os.walk(directory):
        # 使用正则表达式匹配文件名中包含数字的文件
        for file in files:
            if re.search(r'\d', file):
                # 如果文件名中包含数字,将其路径添加到列表中
                file_list.append(os.path.join(root, file))
    # 返回符合条件的文件路径列表
    return file_list

.\numpy\numpy\ma\testutils.py

# 导入Python标准库中的operator模块,用于操作符和函数的标准集合
import operator

# 导入NumPy库,约定使用别名np,提供对多维数组和矩阵的支持
import numpy as np

# 从NumPy中导入ndarray类
from numpy import ndarray

# 导入NumPy核心中的umath模块,提供基本的数学函数
import numpy._core.umath as umath

# 导入NumPy的测试模块
import numpy.testing

# 从NumPy的测试模块中导入指定的函数和类
from numpy.testing import (
    assert_, assert_allclose, assert_array_almost_equal_nulp,
    assert_raises, build_err_msg
    )

# 从当前包的core模块中导入指定的函数和类
from .core import mask_or, getmask, masked_array, nomask, masked, filled

# 定义一个变量,包含一些用于掩码数组和子类测试的杂项函数
__all__masked = [
    'almost', 'approx', 'assert_almost_equal', 'assert_array_almost_equal',
    'assert_array_approx_equal', 'assert_array_compare',
    'assert_array_equal', 'assert_array_less', 'assert_close',
    'assert_equal', 'assert_equal_records', 'assert_mask_equal',
    'assert_not_equal', 'fail_if_array_equal',
    ]

# 包含一些普通的测试函数,以避免破坏错误地包含它们的其他项目,例如SciPy
# 这些函数并非都用于掩码数组,但在此文件中无法区分
from unittest import TestCase

# 定义一个变量,包含一些从测试模块导入的函数和类
__some__from_testing = [
    'TestCase', 'assert_', 'assert_allclose', 'assert_array_almost_equal_nulp',
    'assert_raises'
    ]

# 将所有公开的函数和类组合为__all__变量,以便在包外可见
__all__ = __all__masked + __some__from_testing


# 定义一个函数approx,用于比较两个数组是否在给定的容差范围内相等
def approx(a, b, fill_value=True, rtol=1e-5, atol=1e-8):
    """
    如果a和b的所有元素在给定的容差范围内相等,则返回True。

    如果fill_value为True,则掩码值被视为相等;否则,掩码值被视为不等。
    相对误差rtol应为正数且 << 1.0。绝对误差atol适用于b中非常小或零的元素;它表示a必须多么小。
    """
    # 获取a和b的掩码并合并为一个掩码
    m = mask_or(getmask(a), getmask(b))
    # 获取a和b的实际数据(去除掩码后的数据)
    d1 = filled(a)
    d2 = filled(b)
    # 如果数据类型为对象(O),直接比较是否相等并展平
    if d1.dtype.char == "O" or d2.dtype.char == "O":
        return np.equal(d1, d2).ravel()
    # 将a和b的实际数据填充到掩码数组中,并转换为浮点数类型
    x = filled(
        masked_array(d1, copy=False, mask=m), fill_value
    ).astype(np.float64)
    y = filled(masked_array(d2, copy=False, mask=m), 1).astype(np.float64)
    # 计算x和y之间的相对误差和绝对误差,判断是否在容差范围内
    d = np.less_equal(umath.absolute(x - y), atol + rtol * umath.absolute(y))
    # 返回比较结果并展平
    return d.ravel()


# 定义一个函数almost,用于比较两个数组是否在给定的小数位数内相等
def almost(a, b, decimal=6, fill_value=True):
    """
    如果a和b在小数位数上相等,则返回True。

    如果fill_value为True,则掩码值被视为相等;否则,掩码值被视为不等。
    """
    # 获取a和b的掩码并合并为一个掩码
    m = mask_or(getmask(a), getmask(b))
    # 获取a和b的实际数据(去除掩码后的数据)
    d1 = filled(a)
    d2 = filled(b)
    # 如果数据类型为对象(O),直接比较是否相等并展平
    if d1.dtype.char == "O" or d2.dtype.char == "O":
        return np.equal(d1, d2).ravel()
    # 将a和b的实际数据填充到掩码数组中,并转换为浮点数类型
    x = filled(
        masked_array(d1, copy=False, mask=m), fill_value
    ).astype(np.float64)
    y = filled(masked_array(d2, copy=False, mask=m), 1).astype(np.float64)
    # 比较x和y在小数位数上的精度,判断是否相等
    d = np.around(np.abs(x - y), decimal) <= 10.0 ** (-decimal)
    # 返回比较结果并展平
    return d.ravel()


# 定义一个函数_assert_equal_on_sequences,用于在序列上断言相等
def _assert_equal_on_sequences(actual, desired, err_msg=''):
    """
    在序列上断言actual和desired是否相等。
    """
    Asserts the equality of two non-array sequences.

    """
    # 断言两个非数组序列的长度相等
    assert_equal(len(actual), len(desired), err_msg)
    # 遍历期望结果的长度,逐个断言实际结果和期望结果的每个元素相等
    for k in range(len(desired)):
        assert_equal(actual[k], desired[k], f'item={k!r}\n{err_msg}')
    # 返回
    return
# 检查两个记录是否相等的断言函数
def assert_equal_records(a, b):
    """
    Asserts that two records are equal.

    Pretty crude for now.

    """
    # 断言两个记录的数据类型相等
    assert_equal(a.dtype, b.dtype)
    # 遍历记录中的每个字段
    for f in a.dtype.names:
        # 获取字段 f 的值
        (af, bf) = (operator.getitem(a, f), operator.getitem(b, f))
        # 如果两个字段的值均不为 masked,则断言它们相等
        if not (af is masked) and not (bf is masked):
            assert_equal(operator.getitem(a, f), operator.getitem(b, f))
    return


# 断言两个项是否相等的通用函数
def assert_equal(actual, desired, err_msg=''):
    """
    Asserts that two items are equal.

    """
    # Case #1: 如果 desired 是字典 .....
    if isinstance(desired, dict):
        # 如果 actual 不是字典,抛出断言错误
        if not isinstance(actual, dict):
            raise AssertionError(repr(type(actual)))
        # 断言 actual 和 desired 的长度相等
        assert_equal(len(actual), len(desired), err_msg)
        # 遍历 desired 字典的键值对
        for k, i in desired.items():
            # 如果键 k 不在 actual 中,抛出断言错误
            if k not in actual:
                raise AssertionError(f"{k} not in {actual}")
            # 递归调用 assert_equal 检查 actual[k] 和 desired[k] 是否相等
            assert_equal(actual[k], desired[k], f'key={k!r}\n{err_msg}')
        return
    # Case #2: 如果 desired 是列表或元组 .....
    if isinstance(desired, (list, tuple)) and isinstance(actual, (list, tuple)):
        # 调用 _assert_equal_on_sequences 函数检查序列是否相等
        return _assert_equal_on_sequences(actual, desired, err_msg='')
    # 如果 actual 和 desired 都不是 ndarray,则构建错误消息并断言它们相等
    if not (isinstance(actual, ndarray) or isinstance(desired, ndarray)):
        msg = build_err_msg([actual, desired], err_msg,)
        if not desired == actual:
            raise AssertionError(msg)
        return
    # Case #4: 如果 actual 或 desired 是 masked,抛出 ValueError
    if ((actual is masked) and not (desired is masked)) or \
            ((desired is masked) and not (actual is masked)):
        msg = build_err_msg([actual, desired],
                            err_msg, header='', names=('x', 'y'))
        raise ValueError(msg)
    # 将 actual 和 desired 转换为 ndarray
    actual = np.asanyarray(actual)
    desired = np.asanyarray(desired)
    # 获取 actual 和 desired 的数据类型
    (actual_dtype, desired_dtype) = (actual.dtype, desired.dtype)
    # 如果 actual 和 desired 都是字符串数组,则调用 _assert_equal_on_sequences 检查序列是否相等
    if actual_dtype.char == "S" and desired_dtype.char == "S":
        return _assert_equal_on_sequences(actual.tolist(),
                                          desired.tolist(),
                                          err_msg='')
    # 否则调用 assert_array_equal 函数断言 actual 和 desired 相等
    return assert_array_equal(actual, desired, err_msg)


# 如果两个项相等,则抛出断言错误的函数
def fail_if_equal(actual, desired, err_msg='',):
    """
    Raises an assertion error if two items are equal.

    """
    # 如果 desired 是字典 .....
    if isinstance(desired, dict):
        # 如果 actual 不是字典,抛出断言错误
        if not isinstance(actual, dict):
            raise AssertionError(repr(type(actual)))
        # 调用 fail_if_equal 检查 actual 和 desired 的长度是否相等
        fail_if_equal(len(actual), len(desired), err_msg)
        # 遍历 desired 字典的键值对
        for k, i in desired.items():
            # 如果键 k 不在 actual 中,抛出断言错误
            if k not in actual:
                raise AssertionError(repr(k))
            # 递归调用 fail_if_equal 检查 actual[k] 和 desired[k] 是否不相等
            fail_if_equal(actual[k], desired[k], f'key={k!r}\n{err_msg}')
        return
    # 如果 desired 是列表或元组 .....
    if isinstance(desired, (list, tuple)) and isinstance(actual, (list, tuple)):
        # 调用 fail_if_equal 检查 actual 和 desired 的长度是否相等
        fail_if_equal(len(actual), len(desired), err_msg)
        # 遍历列表或元组的每个元素,递归调用 fail_if_equal 检查它们是否不相等
        for k in range(len(desired)):
            fail_if_equal(actual[k], desired[k], f'item={k!r}\n{err_msg}')
        return
    # 如果 actual 或 desired 是 ndarray,则调用 fail_if_array_equal 检查它们是否不相等
    if isinstance(actual, np.ndarray) or isinstance(desired, np.ndarray):
        return fail_if_array_equal(actual, desired, err_msg)
    # 调用 build_err_msg 函数,生成错误信息字符串
    msg = build_err_msg([actual, desired], err_msg)
    # 如果 desired 不等于 actual,抛出 AssertionError 异常,异常信息为 msg
    if not desired != actual:
        raise AssertionError(msg)
# 将 assert_not_equal 定义为 fail_if_equal 的别名
assert_not_equal = fail_if_equal


def assert_almost_equal(actual, desired, decimal=7, err_msg='', verbose=True):
    """
    Asserts that two items are almost equal.

    The test is equivalent to abs(desired-actual) < 0.5 * 10**(-decimal).

    """
    # 如果 actual 或 desired 是 NumPy 数组,则调用 assert_array_almost_equal 函数进行比较
    if isinstance(actual, np.ndarray) or isinstance(desired, np.ndarray):
        return assert_array_almost_equal(actual, desired, decimal=decimal,
                                         err_msg=err_msg, verbose=verbose)
    # 否则,构建错误消息
    msg = build_err_msg([actual, desired],
                        err_msg=err_msg, verbose=verbose)
    # 如果 abs(desired - actual) 不小于 10**(-decimal),则抛出 AssertionError
    if not round(abs(desired - actual), decimal) == 0:
        raise AssertionError(msg)


# 将 assert_close 定义为 assert_almost_equal 的别名
assert_close = assert_almost_equal


def assert_array_compare(comparison, x, y, err_msg='', verbose=True, header='',
                         fill_value=True):
    """
    Asserts that comparison between two masked arrays is satisfied.

    The comparison is elementwise.

    """
    # 分配一个公共掩码并重新填充
    m = mask_or(getmask(x), getmask(y))
    # 创建掩码数组 x 和 y
    x = masked_array(x, copy=False, mask=m, keep_mask=False, subok=False)
    y = masked_array(y, copy=False, mask=m, keep_mask=False, subok=False)
    # 如果 x 是掩码数组而 y 不是,或者 y 是掩码数组而 x 不是,则抛出 ValueError
    if ((x is masked) and not (y is masked)) or \
            ((y is masked) and not (x is masked)):
        msg = build_err_msg([x, y], err_msg=err_msg, verbose=verbose,
                            header=header, names=('x', 'y'))
        raise ValueError(msg)
    # 现在对填充版本运行基本测试
    return np.testing.assert_array_compare(comparison,
                                           x.filled(fill_value),
                                           y.filled(fill_value),
                                           err_msg=err_msg,
                                           verbose=verbose, header=header)


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

    """
    # 检查两个掩码数组的逐元素相等性
    assert_array_compare(operator.__eq__, x, y,
                         err_msg=err_msg, verbose=verbose,
                         header='Arrays are not equal')


def fail_if_array_equal(x, y, err_msg='', verbose=True):
    """
    Raises an assertion error if two masked arrays are not equal elementwise.

    """
    # 定义比较函数,如果 x 和 y 不全等,则返回 True
    def compare(x, y):
        return (not np.all(approx(x, y)))
    # 断言两个掩码数组 x 和 y 在逐元素比较时不全相等
    assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
                         header='Arrays are not equal')


def assert_array_approx_equal(x, y, decimal=6, err_msg='', verbose=True):
    """
    Checks the equality of two masked arrays, up to given number odecimals.

    The equality is checked elementwise.

    """
    # 定义比较函数,通过指定的小数位数检查两个掩码数组的近似相等性
    def compare(x, y):
        "Returns the result of the loose comparison between x and y)."
        return approx(x, y, rtol=10. ** -decimal)
    # 断言两个掩码数组 x 和 y 在近似比较时相等
    assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
                         header='Arrays are not almost equal')
# 检查两个带掩码的数组在给定小数位数下的几乎相等性
def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True):
    """
    Checks the equality of two masked arrays, up to given number of decimals.

    The equality is checked elementwise.

    """
    # 定义比较函数,比较 x 和 y 的近似程度,精度为 decimal
    def compare(x, y):
        "Returns the result of the loose comparison between x and y)."
        return almost(x, y, decimal)
    # 调用通用的数组比较函数,比较 x 和 y,检查它们是否几乎相等
    assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,
                         header='Arrays are not almost equal')


# 检查两个数组在元素级别上是否 x 小于 y
def assert_array_less(x, y, err_msg='', verbose=True):
    """
    Checks that x is smaller than y elementwise.

    """
    # 调用通用的数组比较函数,比较 x 和 y,验证 x 是否在元素级别上小于 y
    assert_array_compare(operator.__lt__, x, y,
                         err_msg=err_msg, verbose=verbose,
                         header='Arrays are not less-ordered')


# 断言两个掩码数组的相等性
def assert_mask_equal(m1, m2, err_msg=''):
    """
    Asserts the equality of two masks.

    """
    # 如果 m1 是 nomask,则断言 m2 也是 nomask
    if m1 is nomask:
        assert_(m2 is nomask)
    # 如果 m2 是 nomask,则断言 m1 也是 nomask
    if m2 is nomask:
        assert_(m1 is nomask)
    # 使用通用的数组相等性比较函数,断言 m1 和 m2 在掩码中是相等的
    assert_array_equal(m1, m2, err_msg=err_msg)