NumPy-源码解析-二十-

76 阅读1小时+

NumPy 源码解析(二十)

.\numpy\numpy\lib\_scimath_impl.pyi

# 导入必要的类型提示和函数定义
from typing import overload, Any

# 导入复数浮点数相关模块
from numpy import complexfloating

# 导入类型提示相关模块
from numpy._typing import (
    NDArray,
    _ArrayLikeFloat_co,
    _ArrayLikeComplex_co,
    _ComplexLike_co,
    _FloatLike_co,
)

# 指定在此模块中可导出的公共接口列表
__all__: list[str]

# 平方根函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def sqrt(x: _FloatLike_co) -> Any: ...

@overload
def sqrt(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def sqrt(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def sqrt(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 对数函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def log(x: _FloatLike_co) -> Any: ...

@overload
def log(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def log(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def log(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 以10为底的对数函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def log10(x: _FloatLike_co) -> Any: ...

@overload
def log10(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def log10(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def log10(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 以2为底的对数函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def log2(x: _FloatLike_co) -> Any: ...

@overload
def log2(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def log2(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def log2(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 自定义底数的对数函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def logn(n: _FloatLike_co, x: _FloatLike_co) -> Any: ...

@overload
def logn(n: _ComplexLike_co, x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def logn(n: _ArrayLikeFloat_co, x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def logn(n: _ArrayLikeComplex_co, x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 幂函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def power(x: _FloatLike_co, p: _FloatLike_co) -> Any: ...

@overload
def power(x: _ComplexLike_co, p: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def power(x: _ArrayLikeFloat_co, p: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def power(x: _ArrayLikeComplex_co, p: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 反余弦函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def arccos(x: _FloatLike_co) -> Any: ...

@overload
def arccos(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def arccos(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def arccos(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 反正弦函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def arcsin(x: _FloatLike_co) -> Any: ...

@overload
def arcsin(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def arcsin(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def arcsin(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

# 反双曲正切函数的函数重载,根据不同输入类型返回不同类型的值
@overload
def arctanh(x: _FloatLike_co) -> Any: ...

@overload
def arctanh(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...

@overload
def arctanh(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...

@overload
def arctanh(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...

.\numpy\numpy\lib\_shape_base_impl.py

# 导入 functools 模块,用于创建偏函数
import functools
# 导入 warnings 模块,用于警告处理
import warnings

# 导入 numpy 库的部分子模块和函数
# 从 numpy 的核心数值计算模块中导入特定函数和类
import numpy._core.numeric as _nx
# 从 numpy 的核心数值计算模块中导入 asarray、zeros、zeros_like、array、asanyarray 函数
from numpy._core.numeric import asarray, zeros, zeros_like, array, asanyarray
# 从 numpy 的核心数组处理模块中导入 reshape、transpose 函数
from numpy._core.fromnumeric import reshape, transpose
# 从 numpy 的核心多维数组模块中导入 normalize_axis_index 函数
from numpy._core.multiarray import normalize_axis_index
# 从 numpy 的核心数学计算模块中导入 _array_converter 函数
from numpy._core._multiarray_umath import _array_converter
# 从 numpy 的核心模块中导入 overrides 模块
from numpy._core import overrides
# 从 numpy 的核心模块中导入 vstack、atleast_3d 函数
from numpy._core import vstack, atleast_3d
# 从 numpy 的核心数值计算模块中导入 normalize_axis_tuple 函数
from numpy._core.numeric import normalize_axis_tuple
# 从 numpy 的核心模块中导入 set_module 函数
from numpy._core.overrides import set_module
# 从 numpy 的核心形状基础模块中导入 _arrays_for_stack_dispatcher 函数
from numpy._core.shape_base import _arrays_for_stack_dispatcher
# 从 numpy 的核心索引技巧实现模块中导入 ndindex 函数
from numpy.lib._index_tricks_impl import ndindex
# 从 numpy 的矩阵库中导入 matrix 类
from numpy.matrixlib.defmatrix import matrix  # this raises all the right alarm bells

# 定义 __all__ 变量,包含导出的函数和类名列表
__all__ = [
    'column_stack', 'row_stack', 'dstack', 'array_split', 'split',
    'hsplit', 'vsplit', 'dsplit', 'apply_over_axes', 'expand_dims',
    'apply_along_axis', 'kron', 'tile', 'take_along_axis',
    'put_along_axis'
    ]

# 创建 array_function_dispatch 变量,为 numpy 中函数分派的偏函数
array_function_dispatch = functools.partial(
    overrides.array_function_dispatch, module='numpy')


def _make_along_axis_idx(arr_shape, indices, axis):
    # 计算用于迭代的维度
    # 检查 indices 是否为整数数组的子类型,否则引发错误
    if not _nx.issubdtype(indices.dtype, _nx.integer):
        raise IndexError('`indices` must be an integer array')
    # 检查 indices 和 arr 是否具有相同的维度数,否则引发错误
    if len(arr_shape) != indices.ndim:
        raise ValueError(
            "`indices` and `arr` must have the same number of dimensions")
    # 创建形状全为 1 的元组 shape_ones
    shape_ones = (1,) * indices.ndim
    # 构建目标维度列表 dest_dims,插入 None 在指定的轴上
    dest_dims = list(range(axis)) + [None] + list(range(axis+1, indices.ndim))

    # 构建一个花式索引 fancy_index,包含正交 arange,请求的索引插入到正确的位置
    fancy_index = []
    for dim, n in zip(dest_dims, arr_shape):
        if dim is None:
            fancy_index.append(indices)
        else:
            ind_shape = shape_ones[:dim] + (-1,) + shape_ones[dim+1:]
            fancy_index.append(_nx.arange(n).reshape(ind_shape))

    return tuple(fancy_index)


def _take_along_axis_dispatcher(arr, indices, axis):
    # 返回 arr 和 indices 的元组,用于 take_along_axis 函数的分派
    return (arr, indices)


@array_function_dispatch(_take_along_axis_dispatcher)
def take_along_axis(arr, indices, axis):
    """
    通过匹配 1 维索引和数据切片,从输入数组中取值。

    这将沿着指定轴迭代匹配的索引和数据数组中的 1 维切片,并使用前者查找后者中的值。这些切片可以具有不同的长度。

    返回一个由匹配的数组组成的新数组。

    .. versionadded:: 1.15.0

    Parameters
    ----------
    arr : ndarray (Ni..., M, Nk...)
        源数组
    indices : ndarray (Ni..., J, Nk...)
        沿着 `arr` 的每个 1 维切片取出的索引。它必须与 `arr` 的维度匹配,
        但 Ni 和 Nj 只需要广播至 `arr`。

    """
    # normalize inputs
    # 如果 axis 参数为 None,则将输入数组视为展平后的一维数组,以保持与 `sort` 和 `argsort` 的一致性
    if axis is None:
        # 如果 indices 不是一维数组,则抛出 ValueError 异常
        if indices.ndim != 1:
            raise ValueError(
                'when axis=None, `indices` must have a single dimension.')
        arr = arr.flat  # 将 arr 展平为一维数组
        arr_shape = (len(arr),)  # 获取展平后数组的长度,因为 flatiter 没有 .shape 属性
        axis = 0  # 将 axis 设置为 0
    else:
        # 规范化 axis 参数的值,确保其在有效范围内
        axis = normalize_axis_index(axis, arr.ndim)
        arr_shape = arr.shape  # 获取数组的形状信息

    # use the fancy index
    # 使用 _make_along_axis_idx 函数根据给定的 axis 和 indices 创建沿指定轴的索引
    return arr[_make_along_axis_idx(arr_shape, indices, axis)]
# 分发器函数,返回传递给 `put_along_axis` 函数的参数元组 (arr, indices, values)
def _put_along_axis_dispatcher(arr, indices, values, axis):
    return (arr, indices, values)

# 装饰器函数,用于分发 `_put_along_axis_dispatcher` 函数的结果到 `put_along_axis` 函数
@array_function_dispatch(_put_along_axis_dispatcher)
def put_along_axis(arr, indices, values, axis):
    """
    将值插入到目标数组中,通过匹配1维索引和数据切片。

    这个函数沿着指定轴迭代匹配的1维切片,使用索引数组将值放入数据数组中。这些切片可以是不同长度的。

    返回沿轴产生索引的函数,如 `argsort` 和 `argpartition`,可以生成适合此函数使用的索引。

    .. versionadded:: 1.15.0

    Parameters
    ----------
    arr : ndarray (Ni..., M, Nk...)
        目标数组。
    indices : ndarray (Ni..., J, Nk...)
        要在 `arr` 的每个1维切片上更改的索引。它必须与 `arr` 的维度匹配,但 Ni 和 Nj 中的维度可以是 1,以便与 `arr` 广播。
    values : array_like (Ni..., J, Nk...)
        要插入到这些索引处的值。其形状和维度会广播以匹配 `indices`。
    axis : int
        要沿其获取1维切片的轴。如果 `axis` 是 None,则将目标数组视为其已创建的展平1维视图。

    Notes
    -----
    这相当于(但比)`ndindex` 和 `s_` 的以下用法更快,它设置 `ii` 和 `kk` 的每个值为索引元组:

        Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:]
        J = indices.shape[axis]  # 可能不等于 M

        for ii in ndindex(Ni):
            for kk in ndindex(Nk):
                a_1d       = a      [ii + s_[:,] + kk]
                indices_1d = indices[ii + s_[:,] + kk]
                values_1d  = values [ii + s_[:,] + kk]
                for j in range(J):
                    a_1d[indices_1d[j]] = values_1d[j]

    或者等效地,消除内部循环,最后两行将是:

                a_1d[indices_1d] = values_1d

    See Also
    --------
    take_along_axis :
        通过匹配1维索引和数据切片从输入数组中获取值

    Examples
    --------

    对于这个示例数组

    >>> a = np.array([[10, 30, 20], [60, 40, 50]])

    我们可以用以下代码将最大值替换为:

    >>> ai = np.argmax(a, axis=1, keepdims=True)
    >>> ai
    array([[1],
           [0]])
    >>> np.put_along_axis(a, ai, 99, axis=1)
    >>> a
    array([[10, 99, 20],
           [99, 40, 50]])

    """
    # 规范化输入
    if axis is None:
        if indices.ndim != 1:
            raise ValueError(
                '当 `axis=None` 时,`indices` 必须具有单个维度。')
        arr = arr.flat
        axis = 0
        arr_shape = (len(arr),)  # flatiter 没有 .shape
    else:
        axis = normalize_axis_index(axis, arr.ndim)
        arr_shape = arr.shape

    # 使用高级索引
    arr[_make_along_axis_idx(arr_shape, indices, axis)] = values
# 定义一个调度函数,用于应用在给定轴向上的1维切片
def _apply_along_axis_dispatcher(func1d, axis, arr, *args, **kwargs):
    # 直接返回输入数组arr
    return (arr,)


# 使用装饰器进行分派,以支持不同的数据类型和参数组合
@array_function_dispatch(_apply_along_axis_dispatcher)
def apply_along_axis(func1d, axis, arr, *args, **kwargs):
    """
    Apply a function to 1-D slices along the given axis.

    Execute `func1d(a, *args, **kwargs)` where `func1d` operates on 1-D arrays
    and `a` is a 1-D slice of `arr` along `axis`.

    This is equivalent to (but faster than) the following use of `ndindex` and
    `s_`, which sets each of ``ii``, ``jj``, and ``kk`` to a tuple of indices::

        Ni, Nk = a.shape[:axis], a.shape[axis+1:]
        for ii in ndindex(Ni):
            for kk in ndindex(Nk):
                f = func1d(arr[ii + s_[:,] + kk])
                Nj = f.shape
                for jj in ndindex(Nj):
                    out[ii + jj + kk] = f[jj]

    Equivalently, eliminating the inner loop, this can be expressed as::

        Ni, Nk = a.shape[:axis], a.shape[axis+1:]
        for ii in ndindex(Ni):
            for kk in ndindex(Nk):
                out[ii + s_[...,] + kk] = func1d(arr[ii + s_[:,] + kk])

    Parameters
    ----------
    func1d : function (M,) -> (Nj...)
        This function should accept 1-D arrays. It is applied to 1-D
        slices of `arr` along the specified axis.
    axis : integer
        Axis along which `arr` is sliced.
    arr : ndarray (Ni..., M, Nk...)
        Input array.
    args : any
        Additional arguments to `func1d`.
    kwargs : any
        Additional named arguments to `func1d`.

        .. versionadded:: 1.9.0


    Returns
    -------
    out : ndarray  (Ni..., Nj..., Nk...)
        The output array. The shape of `out` is identical to the shape of
        `arr`, except along the `axis` dimension. This axis is removed, and
        replaced with new dimensions equal to the shape of the return value
        of `func1d`. So if `func1d` returns a scalar `out` will have one
        fewer dimensions than `arr`.

    See Also
    --------
    apply_over_axes : Apply a function repeatedly over multiple axes.

    Examples
    --------
    >>> def my_func(a):
    ...     \"\"\"Average first and last element of a 1-D array\"\"\"
    ...     return (a[0] + a[-1]) * 0.5
    >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
    >>> np.apply_along_axis(my_func, 0, b)
    array([4., 5., 6.])
    >>> np.apply_along_axis(my_func, 1, b)
    array([2.,  5.,  8.])

    For a function that returns a 1D array, the number of dimensions in
    `outarr` is the same as `arr`.

    >>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
    >>> np.apply_along_axis(sorted, 1, b)
    array([[1, 7, 8],
           [3, 4, 9],
           [2, 5, 6]])

    For a function that returns a higher dimensional array, those dimensions
    are inserted in place of the `axis` dimension.

    >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
    >>> np.apply_along_axis(np.diag, -1, b)
    """
    # 函数体已经在文档字符串中详细解释了其功能和实现方式,因此无需额外注释
    array([[[1, 0, 0],
            [0, 2, 0],
            [0, 0, 3]],
           [[4, 0, 0],
            [0, 5, 0],
            [0, 0, 6]],
           [[7, 0, 0],
            [0, 8, 0],
            [0, 0, 9]]])
    """
    # 处理负轴索引
    conv = _array_converter(arr)
    # 将处理后的数组赋值给arr
    arr = conv[0]

    # 获取数组的维度
    nd = arr.ndim
    # 规范化轴索引,确保axis在有效范围内
    axis = normalize_axis_index(axis, nd)

    # 将迭代轴放置在数组维度的末尾
    in_dims = list(range(nd))
    inarr_view = transpose(arr, in_dims[:axis] + in_dims[axis+1:] + [axis])

    # 计算迭代轴的索引,并在末尾添加省略号,以防止0维数组退化为标量,从而修复gh-8642
    inds = ndindex(inarr_view.shape[:-1])
    inds = (ind + (Ellipsis,) for ind in inds)

    # 在第一个项目上调用函数
    try:
        ind0 = next(inds)
    except StopIteration:
        raise ValueError(
            'Cannot apply_along_axis when any iteration dimensions are 0'
        ) from None
    # 对inarr_view[ind0]应用func1d函数,*args和**kwargs是可选的额外参数
    res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))

    # 构建一个缓冲区用于存储func1d的评估结果。
    # 删除请求的轴,并在末尾添加新的轴,使得每次写操作都是连续的。
    if not isinstance(res, matrix):
        buff = zeros_like(res, shape=inarr_view.shape[:-1] + res.shape)
    else:
        # 矩阵在重塑时可能会出现问题,所以这里不保留它们。
        buff = zeros(inarr_view.shape[:-1] + res.shape, dtype=res.dtype)

    # 轴的排列,以便out = buff.transpose(buff_permute)
    buff_dims = list(range(buff.ndim))
    buff_permute = (
        buff_dims[0 : axis] +
        buff_dims[buff.ndim-res.ndim : buff.ndim] +
        buff_dims[axis : buff.ndim-res.ndim]
    )

    # 保存第一个结果,然后计算并保存所有剩余结果
    buff[ind0] = res
    for ind in inds:
        buff[ind] = asanyarray(func1d(inarr_view[ind], *args, **kwargs))

    # 对buff进行转置,使用buff_permute重新排列轴,得到最终结果res
    res = transpose(buff, buff_permute)
    # 将结果进行包装并返回
    return conv.wrap(res)
# 用于分发给定函数的轴参数,返回输入数组 `a` 的元组
def _apply_over_axes_dispatcher(func, a, axes):
    return (a,)


# 应用函数到多个轴上的分发器装饰器
@array_function_dispatch(_apply_over_axes_dispatcher)
def apply_over_axes(func, a, axes):
    """
    Apply a function repeatedly over multiple axes.

    `func` is called as `res = func(a, axis)`, where `axis` is the first
    element of `axes`.  The result `res` of the function call must have
    either the same dimensions as `a` or one less dimension.  If `res`
    has one less dimension than `a`, a dimension is inserted before
    `axis`.  The call to `func` is then repeated for each axis in `axes`,
    with `res` as the first argument.

    Parameters
    ----------
    func : function
        This function must take two arguments, `func(a, axis)`.
    a : array_like
        Input array.
    axes : array_like
        Axes over which `func` is applied; the elements must be integers.

    Returns
    -------
    apply_over_axis : ndarray
        The output array.  The number of dimensions is the same as `a`,
        but the shape can be different.  This depends on whether `func`
        changes the shape of its output with respect to its input.

    See Also
    --------
    apply_along_axis :
        Apply a function to 1-D slices of an array along the given axis.

    Notes
    -----
    This function is equivalent to tuple axis arguments to reorderable ufuncs
    with keepdims=True. Tuple axis arguments to ufuncs have been available since
    version 1.7.0.

    Examples
    --------
    >>> a = np.arange(24).reshape(2,3,4)
    >>> a
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]],
           [[12, 13, 14, 15],
            [16, 17, 18, 19],
            [20, 21, 22, 23]]])

    Sum over axes 0 and 2. The result has same number of dimensions
    as the original array:

    >>> np.apply_over_axes(np.sum, a, [0,2])
    array([[[ 60],
            [ 92],
            [124]]])

    Tuple axis arguments to ufuncs are equivalent:

    >>> np.sum(a, axis=(0,2), keepdims=True)
    array([[[ 60],
            [ 92],
            [124]]])

    """
    # 将输入数组 `a` 转换为 ndarray 类型
    val = asarray(a)
    # 获取输入数组 `a` 的维度数
    N = a.ndim
    # 如果轴参数 `axes` 的维度为0,则转换为元组
    if array(axes).ndim == 0:
        axes = (axes,)
    # 遍历每个轴参数 `axes` 中的轴
    for axis in axes:
        # 如果轴为负数,将其转换为对应的非负数索引
        if axis < 0:
            axis = N + axis
        # 构造函数调用的参数元组
        args = (val, axis)
        # 调用给定函数 `func`,将结果保存为 `res`
        res = func(*args)
        # 如果结果 `res` 的维度与输入数组 `val` 的维度相同,则更新 `val`
        if res.ndim == val.ndim:
            val = res
        # 否则,在指定轴前插入新维度,并更新 `val`
        else:
            res = expand_dims(res, axis)
            # 如果插入新维度后 `res` 的维度与输入数组 `val` 的维度相同,则更新 `val`
            if res.ndim == val.ndim:
                val = res
            # 否则,抛出值错误,指示函数未返回正确形状的数组
            else:
                raise ValueError("function is not returning "
                                 "an array of the correct shape")
    # 返回最终处理结果 `val`
    return val


# 用于分发给定数组和轴参数的装饰器,返回输入数组 `a` 的元组
def _expand_dims_dispatcher(a, axis):
    return (a,)


# 插入新轴以扩展数组形状的函数
@array_function_dispatch(_expand_dims_dispatcher)
def expand_dims(a, axis):
    """
    Expand the shape of an array.

    Insert a new axis that will appear at the `axis` position in the expanded
    array shape.

    Parameters
    ----------
    a : array_like
        Input array.

    """
    # 如果输入的数组 `a` 是矩阵类型,将其转换为 ndarray 类型
    if isinstance(a, matrix):
        a = asarray(a)
    else:
        # 否则,将输入的数组 `a` 转换为任意数组类型
        a = asanyarray(a)

    # 如果输入的轴 `axis` 不是 tuple 或者 list 类型,转换为 tuple 类型
    if type(axis) not in (tuple, list):
        axis = (axis,)

    # 计算输出数组的维度,为输入数组的维度加上 `axis` 的长度
    out_ndim = len(axis) + a.ndim

    # 根据输入的轴 `axis` 和输出的维度 `out_ndim`,规范化轴元组
    axis = normalize_axis_tuple(axis, out_ndim)

    # 创建一个迭代器用于输入数组 `a` 的形状
    shape_it = iter(a.shape)
    # 根据输入的轴 `axis` 和输出的维度 `out_ndim`,生成输出数组的形状
    shape = [1 if ax in axis else next(shape_it) for ax in range(out_ndim)]

    # 将输入数组 `a` 按照生成的形状 `shape` 进行重塑,并返回结果
    return a.reshape(shape)
# NOTE: Remove once deprecation period passes
# 设置模块为 "numpy",这在 NumPy 中用于一些内部操作
@set_module("numpy")
# 定义函数 `row_stack`,用于堆叠数组的行,已被弃用,将在 NumPy 2.0 中删除,预计在 2023-08-18 弃用
def row_stack(tup, *, dtype=None, casting="same_kind"):
    # 发出警告,提示用户 `row_stack` 已弃用,建议直接使用 `np.vstack`
    warnings.warn(
        "`row_stack` alias is deprecated. "
        "Use `np.vstack` directly.",
        DeprecationWarning,
        stacklevel=2
    )
    # 调用 `vstack` 函数进行实际的堆叠操作
    return vstack(tup, dtype=dtype, casting=casting)


# 将 `row_stack` 函数的文档字符串设置为 `vstack` 函数的文档字符串
row_stack.__doc__ = vstack.__doc__


# 定义 `_column_stack_dispatcher` 函数,用于分派给 `_arrays_for_stack_dispatcher` 函数
def _column_stack_dispatcher(tup):
    return _arrays_for_stack_dispatcher(tup)


# 使用 `array_function_dispatch` 装饰器,定义 `column_stack` 函数
@array_function_dispatch(_column_stack_dispatcher)
# `column_stack` 函数用于将多个一维数组或二维数组按列堆叠成二维数组
def column_stack(tup):
    """
    Stack 1-D arrays as columns into a 2-D array.

    Take a sequence of 1-D arrays and stack them as columns
    to make a single 2-D array. 2-D arrays are stacked as-is,
    just like with `hstack`.  1-D arrays are turned into 2-D columns
    first.

    Parameters
    ----------
    tup : sequence of 1-D or 2-D arrays.
        Arrays to stack. All of them must have the same first dimension.

    Returns
    -------
    stacked : 2-D array
        The array formed by stacking the given arrays.

    See Also
    --------
    stack, hstack, vstack, concatenate

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

    """
    arrays = []
    # 遍历输入的数组序列
    for v in tup:
        # 将每个元素转换为数组对象
        arr = asanyarray(v)
        # 如果数组的维度小于 2,则将其转置为二维数组的列
        if arr.ndim < 2:
            arr = array(arr, copy=None, subok=True, ndmin=2).T
        # 将处理后的数组添加到数组列表中
        arrays.append(arr)
    # 使用 `_nx.concatenate` 函数在第二维度上连接所有数组,形成最终的堆叠数组
    return _nx.concatenate(arrays, 1)


# 定义 `_dstack_dispatcher` 函数,用于分派给 `_arrays_for_stack_dispatcher` 函数
def _dstack_dispatcher(tup):
    return _arrays_for_stack_dispatcher(tup)


# 使用 `array_function_dispatch` 装饰器,定义 `dstack` 函数
@array_function_dispatch(_dstack_dispatcher)
# `dstack` 函数用于沿着第三个轴(深度方向)堆叠数组序列
def dstack(tup):
    """
    Stack arrays in sequence depth wise (along third axis).

    This is equivalent to concatenation along the third axis after 2-D arrays
    of shape `(M,N)` have been reshaped to `(M,N,1)` and 1-D arrays of shape
    `(N,)` have been reshaped to `(1,N,1)`. Rebuilds arrays divided by
    `dsplit`.

    This function makes most sense for arrays with up to 3 dimensions. For
    instance, for pixel-data with a height (first axis), width (second axis),
    and r/g/b channels (third axis). The functions `concatenate`, `stack` and
    `block` provide more general stacking and concatenation operations.

    Parameters
    ----------
    tup : sequence of arrays
        The arrays must have the same shape along all but the third axis.
        1-D or 2-D arrays must have the same shape.

    Returns
    -------
    stacked : ndarray
        The array formed by stacking the given arrays, will be at least 3-D.

    See Also
    --------
    concatenate : Join a sequence of arrays along an existing axis.
    stack : Join a sequence of arrays along a new axis.
    block : Assemble an nd-array from nested lists of blocks.
    vstack : Stack arrays in sequence vertically (row wise).
    hstack : Stack arrays in sequence horizontally (column wise).

    """
    # 为了深度堆叠,将每个数组扩展到至少三维,然后沿第三个轴连接它们
    return concatenate([atleast_3d(_m) for _m in tup], axis=2)
    # column_stack函数:将多个一维数组按列堆叠成一个二维数组。
    # dsplit函数:沿着第三个轴(即深度方向)分割数组。

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

    >>> a = np.array([[1],[2],[3]])
    >>> b = np.array([[2],[3],[4]])
    >>> np.dstack((a,b))
    array([[[1, 2]],
           [[2, 3]],
           [[3, 4]]])

    """
    # 将输入的数组tup中的各个数组至少转换为三维数组
    arrs = atleast_3d(*tup)
    # 如果转换后的结果不是一个元组,则将其包装成元组
    if not isinstance(arrs, tuple):
        arrs = (arrs,)
    # 沿着第三个轴(深度方向)连接所有数组,形成结果数组
    return _nx.concatenate(arrs, 2)
# 将传入的数组中所有零元素替换为与其相同类型的空数组
def _replace_zero_by_x_arrays(sub_arys):
    for i in range(len(sub_arys)):
        # 检查当前子数组的维度是否为零
        if _nx.ndim(sub_arys[i]) == 0:
            # 如果是零维数组,将其替换为一个空数组,数据类型与原数组相同
            sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
        elif _nx.sometrue(_nx.equal(_nx.shape(sub_arys[i]), 0)):
            # 如果子数组的形状中有任何一个维度为零,同样替换为一个空数组
            sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
    return sub_arys


# 将传入的参数直接返回,用于分派数组分割操作
def _array_split_dispatcher(ary, indices_or_sections, axis=None):
    return (ary, indices_or_sections)


@array_function_dispatch(_array_split_dispatcher)
def array_split(ary, indices_or_sections, axis=0):
    """
    将数组分割成多个子数组。

    请参考“split”文档。这两个函数之间唯一的区别在于,
    “array_split”允许“indices_or_sections”是一个整数,而不需要等分轴。
    对于长度为l的数组,应该分割为n个部分,它返回l % n个大小为l//n + 1的子数组,
    和其余大小为l//n的子数组。

    参见
    --------
    split : 将数组等分成多个子数组。

    示例
    --------
    >>> x = np.arange(8.0)
    >>> np.array_split(x, 3)
    [array([0.,  1.,  2.]), array([3.,  4.,  5.]), array([6.,  7.])]

    >>> x = np.arange(9)
    >>> np.array_split(x, 4)
    [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])]

    """
    try:
        Ntotal = ary.shape[axis]
    except AttributeError:
        Ntotal = len(ary)
    try:
        # 处理数组情况。
        Nsections = len(indices_or_sections) + 1
        div_points = [0] + list(indices_or_sections) + [Ntotal]
    except TypeError:
        # indices_or_sections 是标量,而不是数组。
        Nsections = int(indices_or_sections)
        if Nsections <= 0:
            raise ValueError('number sections must be larger than 0.') from None
        Neach_section, extras = divmod(Ntotal, Nsections)
        section_sizes = ([0] +
                         extras * [Neach_section+1] +
                         (Nsections-extras) * [Neach_section])
        div_points = _nx.array(section_sizes, dtype=_nx.intp).cumsum()

    sub_arys = []
    sary = _nx.swapaxes(ary, axis, 0)
    for i in range(Nsections):
        st = div_points[i]
        end = div_points[i + 1]
        sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0))

    return sub_arys


# 将传入的参数直接返回,用于分派数组分割操作
def _split_dispatcher(ary, indices_or_sections, axis=None):
    return (ary, indices_or_sections)


@array_function_dispatch(_split_dispatcher)
def split(ary, indices_or_sections, axis=0):
    """
    将数组分割成多个作为视图的子数组。

    参数
    ----------
    ary : ndarray
        要分割成子数组的数组。
    try:
        # 尝试获取 `indices_or_sections` 的长度,如果无法获取则抛出 TypeError 异常
        len(indices_or_sections)
    except TypeError:
        # 如果无法获取长度,说明 `indices_or_sections` 是一个整数,将其作为 `sections`
        sections = indices_or_sections
        # 获取数组 `ary` 在指定轴 `axis` 上的长度
        N = ary.shape[axis]
        # 如果数组长度不能被 `sections` 整除,抛出 ValueError 异常
        if N % sections:
            raise ValueError(
                'array split does not result in an equal division') from None
    # 调用 `array_split` 函数进行数组分割,并返回分割后的结果
    return array_split(ary, indices_or_sections, axis)
# 定义一个分发函数,用于处理 hsplit 和 vsplit 函数的分派逻辑
def _hvdsplit_dispatcher(ary, indices_or_sections):
    return (ary, indices_or_sections)


# 使用装饰器将 _hvdsplit_dispatcher 注册为 hsplit 函数的分发函数
@array_function_dispatch(_hvdsplit_dispatcher)
def hsplit(ary, indices_or_sections):
    """
    将数组沿水平方向(列方向)分割为多个子数组。

    请参考 `split` 的文档。`hsplit` 相当于 `split`,其中 ``axis=1``,
    数组始终沿第二轴分割,对于 1-D 数组,则在 ``axis=0`` 处分割。

    See Also
    --------
    split : 将数组分割为多个等大小的子数组。

    Examples
    --------
    >>> x = np.arange(16.0).reshape(4, 4)
    >>> x
    array([[ 0.,   1.,   2.,   3.],
           [ 4.,   5.,   6.,   7.],
           [ 8.,   9.,  10.,  11.],
           [12.,  13.,  14.,  15.]])
    >>> np.hsplit(x, 2)
    [array([[  0.,   1.],
           [  4.,   5.],
           [  8.,   9.],
           [12.,  13.]]),
     array([[  2.,   3.],
           [  6.,   7.],
           [10.,  11.],
           [14.,  15.]])]
    >>> np.hsplit(x, np.array([3, 6]))
    [array([[ 0.,   1.,   2.],
           [ 4.,   5.,   6.],
           [ 8.,   9.,  10.],
           [12.,  13.,  14.]]),
     array([[ 3.],
           [ 7.],
           [11.],
           [15.]]),
     array([], shape=(4, 0), dtype=float64)]

    对于更高维度的数组,分割仍沿第二轴进行。

    >>> x = np.arange(8.0).reshape(2, 2, 2)
    >>> x
    array([[[0.,  1.],
            [2.,  3.]],
           [[4.,  5.],
            [6.,  7.]]])
    >>> np.hsplit(x, 2)
    [array([[[0.,  1.]],
           [[4.,  5.]]]),
     array([[[2.,  3.]],
           [[6.,  7.]]])]

    对于 1-D 数组,分割沿轴 0 进行。

    >>> x = np.array([0, 1, 2, 3, 4, 5])
    >>> np.hsplit(x, 2)
    [array([0, 1, 2]), array([3, 4, 5])]

    """
    # 如果数组维度为 0,则引发错误,hsplit 只适用于至少 1 维的数组
    if _nx.ndim(ary) == 0:
        raise ValueError('hsplit only works on arrays of 1 or more dimensions')
    # 如果数组维度大于 1,则使用 split 函数在第二轴(axis=1)进行分割
    if ary.ndim > 1:
        return split(ary, indices_or_sections, 1)
    else:
        # 对于 1-D 数组,使用 split 函数在轴 0 进行分割
        return split(ary, indices_or_sections, 0)


# 使用装饰器将 _hvdsplit_dispatcher 注册为 vsplit 函数的分发函数
@array_function_dispatch(_hvdsplit_dispatcher)
def vsplit(ary, indices_or_sections):
    """
    将数组沿垂直方向(行方向)分割为多个子数组。

    请参考 `split` 的文档。`vsplit` 相当于 `split`,其中 `axis=0`(默认),
    数组始终沿第一轴进行分割,无论数组的维度如何。

    See Also
    --------
    split : 将数组分割为多个等大小的子数组。

    Examples
    --------
    >>> x = np.arange(16.0).reshape(4, 4)
    >>> x
    array([[ 0.,   1.,   2.,   3.],
           [ 4.,   5.,   6.,   7.],
           [ 8.,   9.,  10.,  11.],
           [12.,  13.,  14.,  15.]])
    >>> np.vsplit(x, 2)
    [array([[0., 1., 2., 3.],
            [4., 5., 6., 7.]]),
     array([[ 8.,  9., 10., 11.],
            [12., 13., 14., 15.]])]
    >>> np.vsplit(x, np.array([3, 6]))

    """
    # vsplit 与 hsplit 类似,但始终在第一轴(axis=0)进行分割
    return split(ary, indices_or_sections, 0)
    [array([[ 0.,  1.,  2.,  3.],
            [ 4.,  5.,  6.,  7.],
            [ 8.,  9., 10., 11.]]),
     array([[12., 13., 14., 15.]]),
     array([], shape=(0, 4), dtype=float64)]

    With a higher dimensional array the split is still along the first axis.

    >>> x = np.arange(8.0).reshape(2, 2, 2)
    >>> x
    array([[[0.,  1.],
            [2.,  3.]],
           [[4.,  5.],
            [6.,  7.]]])
    >>> np.vsplit(x, 2)
    [array([[[0., 1.],
             [2., 3.]]]),
     array([[[4., 5.],
             [6., 7.]]])]

    """
    # 检查输入数组的维度是否小于2,如果是则抛出异常
    if _nx.ndim(ary) < 2:
        raise ValueError('vsplit only works on arrays of 2 or more dimensions')
    # 在第一轴(axis=0)上按照指定的 indices_or_sections 进行分割数组 ary
    return split(ary, indices_or_sections, 0)
@array_function_dispatch(_hvdsplit_dispatcher)
def dsplit(ary, indices_or_sections):
    """
    Split array into multiple sub-arrays along the 3rd axis (depth).

    Please refer to the `split` documentation.  `dsplit` is equivalent
    to `split` with ``axis=2``, the array is always split along the third
    axis provided the array dimension is greater than or equal to 3.

    See Also
    --------
    split : Split an array into multiple sub-arrays of equal size.

    Examples
    --------
    >>> x = np.arange(16.0).reshape(2, 2, 4)
    >>> x
    array([[[ 0.,   1.,   2.,   3.],
            [ 4.,   5.,   6.,   7.]],
           [[ 8.,   9.,  10.,  11.],
            [12.,  13.,  14.,  15.]]])
    >>> np.dsplit(x, 2)
    [array([[[ 0.,  1.],
            [ 4.,  5.]],
           [[ 8.,  9.],
            [12., 13.]]]), array([[[ 2.,  3.],
            [ 6.,  7.]],
           [[10., 11.],
            [14., 15.]]])]
    >>> np.dsplit(x, np.array([3, 6]))
    [array([[[ 0.,   1.,   2.],
            [ 4.,   5.,   6.]],
           [[ 8.,   9.,  10.],
            [12.,  13.,  14.]]]),
     array([[[ 3.],
            [ 7.]],
           [[11.],
            [15.]]]),
    array([], shape=(2, 2, 0), dtype=float64)]
    """
    # 检查数组的维度是否小于3,如果是则抛出异常
    if _nx.ndim(ary) < 3:
        raise ValueError('dsplit only works on arrays of 3 or more dimensions')
    # 调用split函数,按照指定的轴(第3轴)进行分割
    return split(ary, indices_or_sections, 2)


def get_array_wrap(*args):
    """Find the wrapper for the array with the highest priority.

    In case of ties, leftmost wins. If no wrapper is found, return None.

    .. deprecated:: 2.0
    """

    # 在NumPy 2.0中已弃用,将在2023年7月11日弃用
    warnings.warn(
        "`get_array_wrap` is deprecated. "
        "(deprecated in NumPy 2.0)",
        DeprecationWarning,
        stacklevel=2
    )

    # 根据数组对象的`__array_priority__`属性排序,找到优先级最高的数组包装器
    wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
                 x.__array_wrap__) for i, x in enumerate(args)
                                   if hasattr(x, '__array_wrap__'))
    # 如果找到包装器,则返回优先级最高的包装器
    if wrappers:
        return wrappers[-1][-1]
    # 如果没有找到包装器,则返回None
    return None


def _kron_dispatcher(a, b):
    return (a, b)


@array_function_dispatch(_kron_dispatcher)
def kron(a, b):
    """
    Kronecker product of two arrays.

    Computes the Kronecker product, a composite array made of blocks of the
    second array scaled by the first.

    Parameters
    ----------
    a, b : array_like

    Returns
    -------
    out : ndarray

    See Also
    --------
    outer : The outer product

    Notes
    -----
    The function assumes that the number of dimensions of `a` and `b`
    are the same, if necessary prepending the smallest with ones.
    If ``a.shape = (r0,r1,..,rN)`` and ``b.shape = (s0,s1,...,sN)``,
    the Kronecker product has shape ``(r0*s0, r1*s1, ..., rN*SN)``.
    The elements are products of elements from `a` and `b`, organized
    explicitly by::

        kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN]

    where::

        kt = it * st + jt,  t = 0,...,N


    """
    # 返回由两个数组的Kronecker积构成的新数组
    return _multiarray_umath.c_kron(a, b)
    """
    In the common 2-D case (N=1), the block structure can be visualized::
    
        [[ a[0,0]*b,   a[0,1]*b,  ... , a[0,-1]*b  ],
         [  ...                              ...   ],
         [ a[-1,0]*b,  a[-1,1]*b, ... , a[-1,-1]*b ]]
    
    
    Examples
    --------
    >>> np.kron([1,10,100], [5,6,7])
    array([  5,   6,   7, ..., 500, 600, 700])
    >>> np.kron([5,6,7], [1,10,100])
    array([  5,  50, 500, ...,   7,  70, 700])
    
    >>> np.kron(np.eye(2), np.ones((2,2)))
    array([[1.,  1.,  0.,  0.],
           [1.,  1.,  0.,  0.],
           [0.,  0.,  1.,  1.],
           [0.,  0.,  1.,  1.]])
    
    >>> a = np.arange(100).reshape((2,5,2,5))
    >>> b = np.arange(24).reshape((2,3,4))
    >>> c = np.kron(a,b)
    >>> c.shape
    (2, 10, 6, 20)
    >>> I = (1,3,0,2)
    >>> J = (0,2,1)
    >>> J1 = (0,) + J             # extend to ndim=4
    >>> S1 = (1,) + b.shape
    >>> K = tuple(np.array(I) * np.array(S1) + np.array(J1))
    >>> c[K] == a[I]*b[J]
    True
    
    """
    # Equalise the shapes by prepending smaller array with 1s
    # Expand shapes of both the arrays by adding new axes at odd positions for 1st array and even positions for 2nd
    # Compute the product of the modified arrays
    # The innermost array elements now contain the rows of the Kronecker product
    # Reshape the result to kron's shape, which is the product of shapes of the two arrays.
    b = asanyarray(b)
    a = array(a, copy=None, subok=True, ndmin=b.ndim)
    is_any_mat = isinstance(a, matrix) or isinstance(b, matrix)
    ndb, nda = b.ndim, a.ndim
    nd = max(ndb, nda)
    
    if (nda == 0 or ndb == 0):
        return _nx.multiply(a, b)
    
    as_ = a.shape
    bs = b.shape
    if not a.flags.contiguous:
        a = reshape(a, as_)
    if not b.flags.contiguous:
        b = reshape(b, bs)
    
    # Equalise the shapes by prepending smaller one with 1s
    as_ = (1,)*max(0, ndb-nda) + as_
    bs = (1,)*max(0, nda-ndb) + bs
    
    # Insert empty dimensions
    a_arr = expand_dims(a, axis=tuple(range(ndb-nda)))
    b_arr = expand_dims(b, axis=tuple(range(nda-ndb)))
    
    # Compute the product
    a_arr = expand_dims(a_arr, axis=tuple(range(1, nd*2, 2)))
    b_arr = expand_dims(b_arr, axis=tuple(range(0, nd*2, 2)))
    # In case of `mat`, convert result to `array`
    result = _nx.multiply(a_arr, b_arr, subok=(not is_any_mat))
    
    # Reshape back
    result = result.reshape(_nx.multiply(as_, bs))
    
    return result if not is_any_mat else matrix(result, copy=False)
# 定义一个函数 _tile_dispatcher,用于返回输入参数 A 和 reps
def _tile_dispatcher(A, reps):
    return (A, reps)

# 使用装饰器 array_function_dispatch,将 _tile_dispatcher 函数与 tile 函数关联起来
@array_function_dispatch(_tile_dispatcher)
# 定义 tile 函数,用于构造通过重复 A 组成的数组
def tile(A, reps):
    """
    Construct an array by repeating A the number of times given by reps.

    If `reps` has length ``d``, the result will have dimension of
    ``max(d, A.ndim)``.

    If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
    axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
    or shape (1, 1, 3) for 3-D replication. If this is not the desired
    behavior, promote `A` to d-dimensions manually before calling this
    function.

    If ``A.ndim > d``, `reps` is promoted to `A`.ndim by prepending 1's to it.
    Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
    (1, 1, 2, 2).

    Note : Although tile may be used for broadcasting, it is strongly
    recommended to use numpy's broadcasting operations and functions.

    Parameters
    ----------
    A : array_like
        The input array.
    reps : array_like
        The number of repetitions of `A` along each axis.

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

    See Also
    --------
    repeat : Repeat elements of an array.
    broadcast_to : Broadcast an array to a new shape

    Examples
    --------
    >>> a = np.array([0, 1, 2])
    >>> np.tile(a, 2)
    array([0, 1, 2, 0, 1, 2])
    >>> np.tile(a, (2, 2))
    array([[0, 1, 2, 0, 1, 2],
           [0, 1, 2, 0, 1, 2]])
    >>> np.tile(a, (2, 1, 2))
    array([[[0, 1, 2, 0, 1, 2]],
           [[0, 1, 2, 0, 1, 2]]])

    >>> b = np.array([[1, 2], [3, 4]])
    >>> np.tile(b, 2)
    array([[1, 2, 1, 2],
           [3, 4, 3, 4]])
    >>> np.tile(b, (2, 1))
    array([[1, 2],
           [3, 4],
           [1, 2],
           [3, 4]])

    >>> c = np.array([1,2,3,4])
    >>> np.tile(c,(4,1))
    array([[1, 2, 3, 4],
           [1, 2, 3, 4],
           [1, 2, 3, 4],
           [1, 2, 3, 4]])
    """
    try:
        # 尝试将 reps 转换为元组
        tup = tuple(reps)
    except TypeError:
        # 如果转换失败,则将 reps 包装成元组
        tup = (reps,)
    # 计算 tup 的长度
    d = len(tup)
    if all(x == 1 for x in tup) and isinstance(A, _nx.ndarray):
        # 如果 tup 中所有元素都为 1,并且 A 是 numpy 数组,则进行特定处理
        # 以确保在所有维度上重复次数为 1 时也会进行复制
        return _nx.array(A, copy=True, subok=True, ndmin=d)
    else:
        # 否则,根据输入的 A 创建一个数组,保留原始数据结构
        c = _nx.array(A, copy=None, subok=True, ndmin=d)
    if (d < c.ndim):
        # 如果 tup 的长度小于 c 的维度数,则在 tup 前面填充 1,以匹配 c 的维度
        tup = (1,)*(c.ndim-d) + tup
    # 计算输出数组的形状,通过将 c 的每个维度乘以对应的重复次数得到
    shape_out = tuple(s*t for s, t in zip(c.shape, tup))
    n = c.size
    if n > 0:
        # 如果 c 的大小大于 0,则进行重复操作
        for dim_in, nrep in zip(c.shape, tup):
            if nrep != 1:
                c = c.reshape(-1, n).repeat(nrep, 0)
            n //= dim_in
    # 最终将 c 重新整形为 shape_out 形状的数组,并返回结果
    return c.reshape(shape_out)

.\numpy\numpy\lib\_shape_base_impl.pyi

# 导入系统模块 sys
import sys
# 导入集合抽象基类中的 Callable 和 Sequence 类
from collections.abc import Callable, Sequence
# 导入类型变量 TypeVar、Any,以及 overload 和 SupportsIndex 类型注解
from typing import TypeVar, Any, overload, SupportsIndex, Protocol

# 根据 Python 版本导入不同的类型注解
if sys.version_info >= (3, 10):
    from typing import ParamSpec, Concatenate
else:
    from typing_extensions import ParamSpec, Concatenate

# 导入 NumPy 库,并将其命名为 np
import numpy as np
# 从 NumPy 中导入多个类型,如 generic、integer 等
from numpy import (
    generic,
    integer,
    ufunc,
    unsignedinteger,
    signedinteger,
    floating,
    complexfloating,
    object_,
)

# 从 NumPy 的内部模块 _typing 中导入多个类型别名
from numpy._typing import (
    ArrayLike,
    NDArray,
    _ShapeLike,
    _ArrayLike,
    _ArrayLikeBool_co,
    _ArrayLikeUInt_co,
    _ArrayLikeInt_co,
    _ArrayLikeFloat_co,
    _ArrayLikeComplex_co,
    _ArrayLikeObject_co,
)

# 从 NumPy 的内部模块 _core.shape_base 中导入 vstack 函数
from numpy._core.shape_base import vstack

# 定义类型变量 _P,用于参数规范
_P = ParamSpec("_P")
# 定义类型变量 _SCT,继承自 generic 泛型类型
_SCT = TypeVar("_SCT", bound=generic)

# 定义 _ArrayWrap 协议,描述 __array_wrap__ 方法的签名
class _ArrayWrap(Protocol):
    def __call__(
        self,
        array: NDArray[Any],
        context: None | tuple[ufunc, tuple[Any, ...], int] = ...,
        return_scalar: bool = ...,
        /,
    ) -> Any: ...

# 定义 _SupportsArrayWrap 协议,描述 __array_wrap__ 属性的签名
class _SupportsArrayWrap(Protocol):
    @property
    def __array_wrap__(self) -> _ArrayWrap: ...

# 声明 __all__ 列表,用于模块级别的公开接口
__all__: list[str]

# 定义 take_along_axis 函数,用于在指定轴上获取元素
def take_along_axis(
    arr: _SCT | NDArray[_SCT],
    indices: NDArray[integer[Any]],
    axis: None | int,
) -> NDArray[_SCT]: ...

# 定义 put_along_axis 函数,用于在指定轴上放置元素
def put_along_axis(
    arr: NDArray[_SCT],
    indices: NDArray[integer[Any]],
    values: ArrayLike,
    axis: None | int,
) -> None: ...

# apply_along_axis 函数的函数重载,用于在指定轴上应用函数
@overload
def apply_along_axis(
    func1d: Callable[Concatenate[NDArray[Any], _P], _ArrayLike[_SCT]],
    axis: SupportsIndex,
    arr: ArrayLike,
    *args: _P.args,
    **kwargs: _P.kwargs,
) -> NDArray[_SCT]: ...
@overload
def apply_along_axis(
    func1d: Callable[Concatenate[NDArray[Any], _P], ArrayLike],
    axis: SupportsIndex,
    arr: ArrayLike,
    *args: _P.args,
    **kwargs: _P.kwargs,
) -> NDArray[Any]: ...

# 定义 apply_over_axes 函数,用于在指定轴上应用函数
def apply_over_axes(
    func: Callable[[NDArray[Any], int], NDArray[_SCT]],
    a: ArrayLike,
    axes: int | Sequence[int],
) -> NDArray[_SCT]: ...

# expand_dims 函数的函数重载,用于扩展数组的维度
@overload
def expand_dims(
    a: _ArrayLike[_SCT],
    axis: _ShapeLike,
) -> NDArray[_SCT]: ...
@overload
def expand_dims(
    a: ArrayLike,
    axis: _ShapeLike,
) -> NDArray[Any]: ...

# column_stack 函数的函数重载,用于按列堆叠输入数组
@overload
def column_stack(tup: Sequence[_ArrayLike[_SCT]]) -> NDArray[_SCT]: ...
@overload
def column_stack(tup: Sequence[ArrayLike]) -> NDArray[Any]: ...

# dstack 函数的函数重载,用于按深度堆叠输入数组
@overload
def dstack(tup: Sequence[_ArrayLike[_SCT]]) -> NDArray[_SCT]: ...
@overload
def dstack(tup: Sequence[ArrayLike]) -> NDArray[Any]: ...

# array_split 函数的函数重载,用于在指定轴上分割数组
@overload
def array_split(
    ary: _ArrayLike[_SCT],
    indices_or_sections: _ShapeLike,
    axis: SupportsIndex = ...,
) -> list[NDArray[_SCT]]: ...
@overload
def array_split(
    ary: ArrayLike,
    indices_or_sections: _ShapeLike,
    axis: SupportsIndex = ...,
) -> list[NDArray[Any]]: ...

# split 函数的函数重载,用于在指定轴上分割数组
@overload
def split(
    ary: _ArrayLike[_SCT],
    indices_or_sections: _ShapeLike,
    axis: SupportsIndex = ...,
) -> list[NDArray[_SCT]]: ...
@overload
def split(
    ary: ArrayLike,
    indices_or_sections: _ShapeLike,
    axis: SupportsIndex = ...,


indices_or_sections: _ShapeLike,
axis: SupportsIndex = ...,
# 定义一个类型提示,表明函数返回一个包含 NDArray[Any] 元素的列表
) -> list[NDArray[Any]]: ...

# hsplit 函数的重载定义,接受一个 _ArrayLike[_SCT] 类型的数组 ary 和一个 _ShapeLike 类型的参数 indices_or_sections
@overload
def hsplit(
    ary: _ArrayLike[_SCT],
    indices_or_sections: _ShapeLike,
) -> list[NDArray[_SCT]]: ...
# hsplit 函数的重载定义,接受一个 ArrayLike 类型的数组 ary 和一个 _ShapeLike 类型的参数 indices_or_sections
@overload
def hsplit(
    ary: ArrayLike,
    indices_or_sections: _ShapeLike,
) -> list[NDArray[Any]]: ...

# vsplit 函数的重载定义,接受一个 _ArrayLike[_SCT] 类型的数组 ary 和一个 _ShapeLike 类型的参数 indices_or_sections
@overload
def vsplit(
    ary: _ArrayLike[_SCT],
    indices_or_sections: _ShapeLike,
) -> list[NDArray[_SCT]]: ...
# vsplit 函数的重载定义,接受一个 ArrayLike 类型的数组 ary 和一个 _ShapeLike 类型的参数 indices_or_sections
@overload
def vsplit(
    ary: ArrayLike,
    indices_or_sections: _ShapeLike,
) -> list[NDArray[Any]]: ...

# dsplit 函数的重载定义,接受一个 _ArrayLike[_SCT] 类型的数组 ary 和一个 _ShapeLike 类型的参数 indices_or_sections
@overload
def dsplit(
    ary: _ArrayLike[_SCT],
    indices_or_sections: _ShapeLike,
) -> list[NDArray[_SCT]]: ...
# dsplit 函数的重载定义,接受一个 ArrayLike 类型的数组 ary 和一个 _ShapeLike 类型的参数 indices_or_sections
@overload
def dsplit(
    ary: ArrayLike,
    indices_or_sections: _ShapeLike,
) -> list[NDArray[Any]]: ...

# get_array_wrap 函数的重载定义,接受多个参数,返回 _ArrayWrap 类型或者 None
@overload
def get_array_wrap(*args: _SupportsArrayWrap) -> _ArrayWrap: ...
# get_array_wrap 函数的重载定义,接受任意对象类型的参数,返回 None 或者 _ArrayWrap 类型
@overload
def get_array_wrap(*args: object) -> None | _ArrayWrap: ...

# kron 函数的重载定义,接受两个 _ArrayLikeBool_co 类型的参数 a 和 b,返回一个布尔类型的 NDArray
@overload
def kron(a: _ArrayLikeBool_co, b: _ArrayLikeBool_co) -> NDArray[np.bool]: ...  # type: ignore[misc]
# kron 函数的重载定义,接受两个 _ArrayLikeUInt_co 类型的参数 a 和 b,返回一个无符号整数类型的 NDArray
@overload
def kron(a: _ArrayLikeUInt_co, b: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ...  # type: ignore[misc]
# kron 函数的重载定义,接受两个 _ArrayLikeInt_co 类型的参数 a 和 b,返回一个有符号整数类型的 NDArray
@overload
def kron(a: _ArrayLikeInt_co, b: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...  # type: ignore[misc]
# kron 函数的重载定义,接受两个 _ArrayLikeFloat_co 类型的参数 a 和 b,返回一个浮点数类型的 NDArray
@overload
def kron(a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ...  # type: ignore[misc]
# kron 函数的重载定义,接受两个 _ArrayLikeComplex_co 类型的参数 a 和 b,返回一个复数类型的 NDArray
@overload
def kron(a: _ArrayLikeComplex_co, b: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
# kron 函数的重载定义,接受一个 _ArrayLikeObject_co 类型的参数 a 和一个任意类型的参数 b,返回一个对象类型的 NDArray
@overload
def kron(a: _ArrayLikeObject_co, b: Any) -> NDArray[object_]: ...
# kron 函数的重载定义,接受一个任意类型的参数 a 和一个 _ArrayLikeObject_co 类型的参数 b,返回一个对象类型的 NDArray
@overload
def kron(a: Any, b: _ArrayLikeObject_co) -> NDArray[object_]: ...

# tile 函数的重载定义,接受一个 _ArrayLike[_SCT] 类型的数组 A 和一个整数或整数序列类型的参数 reps,返回一个与 A 类型相同的数组
@overload
def tile(
    A: _ArrayLike[_SCT],
    reps: int | Sequence[int],
) -> NDArray[_SCT]: ...
# tile 函数的重载定义,接受一个 ArrayLike 类型的数组 A 和一个整数或整数序列类型的参数 reps,返回一个任意类型的 NDArray
@overload
def tile(
    A: ArrayLike,
    reps: int | Sequence[int],
) -> NDArray[Any]: ...

.\numpy\numpy\lib\_stride_tricks_impl.py

"""
Utilities that manipulate strides to achieve desirable effects.

An explanation of strides can be found in the :ref:`arrays.ndarray`.

Functions
---------

.. autosummary::
   :toctree: generated/

"""
import numpy as np
from numpy._core.numeric import normalize_axis_tuple
from numpy._core.overrides import array_function_dispatch, set_module

__all__ = ['broadcast_to', 'broadcast_arrays', 'broadcast_shapes']


class DummyArray:
    """Dummy object that just exists to hang __array_interface__ dictionaries
    and possibly keep alive a reference to a base array.
    """

    def __init__(self, interface, base=None):
        self.__array_interface__ = interface
        self.base = base


def _maybe_view_as_subclass(original_array, new_array):
    if type(original_array) is not type(new_array):
        # if input was an ndarray subclass and subclasses were OK,
        # then view the result as that subclass.
        new_array = new_array.view(type=type(original_array))
        # Since we have done something akin to a view from original_array, we
        # should let the subclass finalize (if it has it implemented, i.e., is
        # not None).
        if new_array.__array_finalize__:
            new_array.__array_finalize__(original_array)
    return new_array


@set_module("numpy.lib.stride_tricks")
def as_strided(x, shape=None, strides=None, subok=False, writeable=True):
    """
    Create a view into the array with the given shape and strides.

    .. warning:: This function has to be used with extreme care, see notes.

    Parameters
    ----------
    x : ndarray
        Array to create a new.
    shape : sequence of int, optional
        The shape of the new array. Defaults to ``x.shape``.
    strides : sequence of int, optional
        The strides of the new array. Defaults to ``x.strides``.
    subok : bool, optional
        .. versionadded:: 1.10

        If True, subclasses are preserved.
    writeable : bool, optional
        .. versionadded:: 1.12

        If set to False, the returned array will always be readonly.
        Otherwise it will be writable if the original array was. It
        is advisable to set this to False if possible (see Notes).

    Returns
    -------
    view : ndarray

    See also
    --------
    broadcast_to : broadcast an array to a given shape.
    reshape : reshape an array.
    lib.stride_tricks.sliding_window_view :
        userfriendly and safe function for a creation of sliding window views.

    Notes
    -----
    ``as_strided`` creates a view into the array given the exact strides
    and shape. This means it manipulates the internal data structure of
    ndarray and, if done incorrectly, the array elements can point to
    invalid memory and can corrupt results or crash your program.
    It is advisable to always use the original ``x.strides`` when
    calculating new strides to avoid reliance on a contiguous memory
    layout.
    """
    # 设置所返回数组的默认形状为输入数组的形状
    shape = x.shape if shape is None else shape
    # 设置所返回数组的默认步幅为输入数组的步幅
    strides = x.strides if strides is None else strides
    # 返回一个数组视图,这个函数要谨慎使用,遵循函数中的警告和注意事项
    return np.lib.stride_tricks.as_strided(x, shape=shape, strides=strides, subok=subok, writeable=writeable)
    """
        Furthermore, arrays created with this function often contain self
        overlapping memory, so that two elements are identical.
        Vectorized write operations on such arrays will typically be
        unpredictable. They may even give different results for small, large,
        or transposed arrays.
    
        Since writing to these arrays has to be tested and done with great
        care, you may want to use ``writeable=False`` to avoid accidental write
        operations.
    
        For these reasons it is advisable to avoid ``as_strided`` when
        possible.
    """
    # 首先将输入转换为数组,可能保留子类
    x = np.array(x, copy=None, subok=subok)
    # 获取数组的 __array_interface__,并存储为字典
    interface = dict(x.__array_interface__)
    # 如果指定了形状,则将其设置到接口字典中
    if shape is not None:
        interface['shape'] = tuple(shape)
    # 如果指定了步幅,则将其设置到接口字典中
    if strides is not None:
        interface['strides'] = tuple(strides)
    
    # 创建一个虚拟的 DummyArray 对象,并转换为 NumPy 数组
    array = np.asarray(DummyArray(interface, base=x))
    # 由于通过 `__interface__` 创建的数组不保留结构化 dtype,我们显式设置 dtype
    array.dtype = x.dtype
    
    # 尝试将结果视图返回为原始数组的子类视图
    view = _maybe_view_as_subclass(x, array)
    
    # 如果视图可写而且不允许写入,则将视图设置为不可写
    if view.flags.writeable and not writeable:
        view.flags.writeable = False
    
    # 返回视图对象
    return view
# 定义函数 `_sliding_window_view_dispatcher`,用于分派到适当的函数处理器
def _sliding_window_view_dispatcher(x, window_shape, axis=None, *,
                                    subok=None, writeable=None):
    # 返回输入数组 `x` 本身,表示暂时只做了分派的处理
    return (x,)


# 使用装饰器 `array_function_dispatch`,将函数 `_sliding_window_view_dispatcher` 注册到模块 `numpy.lib.stride_tricks`
@array_function_dispatch(
    _sliding_window_view_dispatcher, module="numpy.lib.stride_tricks"
)
# 定义函数 `sliding_window_view`,创建一个滑动窗口视图,从给定的数组 `x` 中生成
def sliding_window_view(x, window_shape, axis=None, *,
                        subok=False, writeable=False):
    """
    Create a sliding window view into the array with the given window shape.

    Also known as rolling or moving window, the window slides across all
    dimensions of the array and extracts subsets of the array at all window
    positions.

    .. versionadded:: 1.20.0

    Parameters
    ----------
    x : array_like
        Array to create the sliding window view from.
    window_shape : int or tuple of int
        Size of window over each axis that takes part in the sliding window.
        If `axis` is not present, must have same length as the number of input
        array dimensions. Single integers `i` are treated as if they were the
        tuple `(i,)`.
    axis : int or tuple of int, optional
        Axis or axes along which the sliding window is applied.
        By default, the sliding window is applied to all axes and
        `window_shape[i]` will refer to axis `i` of `x`.
        If `axis` is given as a `tuple of int`, `window_shape[i]` will refer to
        the axis `axis[i]` of `x`.
        Single integers `i` are treated as if they were the tuple `(i,)`.
    subok : bool, optional
        If True, sub-classes will be passed-through, otherwise the returned
        array will be forced to be a base-class array (default).
    writeable : bool, optional
        When true, allow writing to the returned view. The default is false,
        as this should be used with caution: the returned view contains the
        same memory location multiple times, so writing to one location will
        cause others to change.

    Returns
    -------
    view : ndarray
        Sliding window view of the array. The sliding window dimensions are
        inserted at the end, and the original dimensions are trimmed as
        required by the size of the sliding window.
        That is, ``view.shape = x_shape_trimmed + window_shape``, where
        ``x_shape_trimmed`` is ``x.shape`` with every entry reduced by one less
        than the corresponding window size.

    See Also
    --------
    lib.stride_tricks.as_strided: A lower-level and less safe routine for
        creating arbitrary views from custom shape and strides.
    broadcast_to: broadcast an array to a given shape.

    Notes
    -----
    For many applications using a sliding window view can be convenient, but
    potentially very slow. Often specialized solutions exist, for example:

    - `scipy.signal.fftconvolve`

    - filtering functions in `scipy.ndimage`

    - moving window functions provided by
      `bottleneck <https://github.com/pydata/bottleneck>`_.
    """
    # 返回滑动窗口视图的 ndarray 对象,通过 numpy 的库函数来实现
    # 参数 `subok` 和 `writeable` 默认为 `False`
    return np.lib.stride_tricks.sliding_window_view(x, window_shape, axis, subok=subok, writeable=writeable)
    """
    As a rough estimate, a sliding window approach with an input size of `N`
    and a window size of `W` will scale as `O(N*W)` where frequently a special
    algorithm can achieve `O(N)`. That means that the sliding window variant
    for a window size of 100 can be a 100 times slower than a more specialized
    version.

    Nevertheless, for small window sizes, when no custom algorithm exists, or
    as a prototyping and developing tool, this function can be a good solution.

    Examples
    --------
    >>> from numpy.lib.stride_tricks import sliding_window_view
    >>> x = np.arange(6)
    >>> x.shape
    (6,)
    >>> v = sliding_window_view(x, 3)
    >>> v.shape
    (4, 3)
    >>> v
    array([[0, 1, 2],
           [1, 2, 3],
           [2, 3, 4],
           [3, 4, 5]])

    This also works in more dimensions, e.g.

    >>> i, j = np.ogrid[:3, :4]
    >>> x = 10*i + j
    >>> x.shape
    (3, 4)
    >>> x
    array([[ 0,  1,  2,  3],
           [10, 11, 12, 13],
           [20, 21, 22, 23]])
    >>> shape = (2,2)
    >>> v = sliding_window_view(x, shape)
    >>> v.shape
    (2, 3, 2, 2)
    >>> v
    array([[[[ 0,  1],
             [10, 11]],
            [[ 1,  2],
             [11, 12]],
            [[ 2,  3],
             [12, 13]]],
           [[[10, 11],
             [20, 21]],
            [[11, 12],
             [21, 22]],
            [[12, 13],
             [22, 23]]]])

    The axis can be specified explicitly:

    >>> v = sliding_window_view(x, 3, 0)
    >>> v.shape
    (1, 4, 3)
    >>> v
    array([[[ 0, 10, 20],
            [ 1, 11, 21],
            [ 2, 12, 22],
            [ 3, 13, 23]]])

    The same axis can be used several times. In that case, every use reduces
    the corresponding original dimension:

    >>> v = sliding_window_view(x, (2, 3), (1, 1))
    >>> v.shape
    (3, 1, 2, 3)
    >>> v
    array([[[[ 0,  1,  2],
             [ 1,  2,  3]]],
           [[[10, 11, 12],
             [11, 12, 13]]],
           [[[20, 21, 22],
             [21, 22, 23]]]])

    Combining with stepped slicing (`::step`), this can be used to take sliding
    views which skip elements:

    >>> x = np.arange(7)
    >>> sliding_window_view(x, 5)[:, ::2]
    array([[0, 2, 4],
           [1, 3, 5],
           [2, 4, 6]])

    or views which move by multiple elements

    >>> x = np.arange(7)
    >>> sliding_window_view(x, 3)[::2, :]
    array([[0, 1, 2],
           [2, 3, 4],
           [4, 5, 6]])

    A common application of `sliding_window_view` is the calculation of running
    statistics. The simplest example is the
    `moving average <https://en.wikipedia.org/wiki/Moving_average>`_:

    >>> x = np.arange(6)
    >>> x.shape
    (6,)
    >>> v = sliding_window_view(x, 3)
    >>> v.shape
    (4, 3)
    >>> v
    array([[0, 1, 2],
           [1, 2, 3],
           [2, 3, 4],
           [3, 4, 5]])
    >>> moving_average = v.mean(axis=-1)
    >>> moving_average
    array([1., 2., 3., 4.])
    """
    Note that a sliding window approach is often **not** optimal (see Notes).
    """
    # 将窗口形状转换为元组,如果window_shape是可迭代对象的话;否则转换为单元素元组
    window_shape = (tuple(window_shape)
                    if np.iterable(window_shape)
                    else (window_shape,))

    # 将输入数组转换为numpy数组,保留可能存在的子类
    x = np.array(x, copy=None, subok=subok)

    # 将窗口形状转换为numpy数组
    window_shape_array = np.array(window_shape)

    # 检查窗口形状数组中是否有负值,若有则引发ValueError异常
    if np.any(window_shape_array < 0):
        raise ValueError('`window_shape` cannot contain negative values')

    # 如果axis为None,则默认使用所有维度的轴
    if axis is None:
        axis = tuple(range(x.ndim))
        # 检查window_shape与x的维度数是否一致,若不一致则引发ValueError异常
        if len(window_shape) != len(axis):
            raise ValueError(f'Since axis is `None`, must provide '
                             f'window_shape for all dimensions of `x`; '
                             f'got {len(window_shape)} window_shape elements '
                             f'and `x.ndim` is {x.ndim}.')
    else:
        # 标准化axis,确保所有轴都在有效范围内
        axis = normalize_axis_tuple(axis, x.ndim, allow_duplicate=True)
        # 检查window_shape与axis的长度是否一致,若不一致则引发ValueError异常
        if len(window_shape) != len(axis):
            raise ValueError(f'Must provide matching length window_shape and '
                             f'axis; got {len(window_shape)} window_shape '
                             f'elements and {len(axis)} axes elements.')

    # 计算输出数组的步幅
    out_strides = x.strides + tuple(x.strides[ax] for ax in axis)

    # 调整输入数组的形状,以确保每个轴上窗口的合法性
    x_shape_trimmed = list(x.shape)
    for ax, dim in zip(axis, window_shape):
        if x_shape_trimmed[ax] < dim:
            raise ValueError(
                'window shape cannot be larger than input array shape')
        x_shape_trimmed[ax] -= dim - 1
    out_shape = tuple(x_shape_trimmed) + window_shape

    # 返回按需切片的数组,以形成窗口视图
    return as_strided(x, strides=out_strides, shape=out_shape,
                      subok=subok, writeable=writeable)
# 将形状参数转换为元组,如果形状是可迭代的,则转换为元组,否则创建只包含一个元素的元组
shape = tuple(shape) if np.iterable(shape) else (shape,)

# 使用给定的参数创建一个新的 NumPy 数组,将 array 转换为数组,不复制数据,允许子类化
array = np.array(array, copy=None, subok=subok)

# 如果形状为空且 array 的形状不为空,则抛出值错误异常,说明无法将非标量广播到标量数组
if not shape and array.shape:
    raise ValueError('cannot broadcast a non-scalar to a scalar array')

# 如果形状中有任何负数元素,则抛出值错误异常,说明广播形状的所有元素必须是非负的
if any(size < 0 for size in shape):
    raise ValueError('all elements of broadcast shape must be non-negative')

# 定义额外参数列表为空列表
extras = []

# 使用 np.nditer 迭代器创建一个迭代器对象 it,以便按照形状 shape 广播 array
it = np.nditer(
    (array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'] + extras,
    op_flags=['readonly'], itershape=shape, order='C')

# 进入迭代器上下文
with it:
    # 从迭代器获取广播后的视图,即 itviews 列表的第一个元素
    broadcast = it.itviews[0]

# 调用 _maybe_view_as_subclass 函数,返回 array 或 broadcast 的可能子类视图
result = _maybe_view_as_subclass(array, broadcast)

# 如果 readonly 为 False 且 array 具有 _writeable_no_warn 标志,则设置 result 的写标志和写警告标志
# 这部分代码将来会被移除
if not readonly and array.flags._writeable_no_warn:
    result.flags.writeable = True
    result.flags._warn_on_write = True

# 返回广播后的结果数组 result
return result
    # 从索引 32 开始,每隔 31 个元素取一个位置进行迭代
    for pos in range(32, len(args), 31):
        # 使用广播(broadcasting)来避免分配完整的数组
        # 具讽刺意味的是,np.broadcast 不能正确处理 np.broadcast 对象(它将它们视为标量)
        b = broadcast_to(0, b.shape)
        # 将广播应用于参数数组的子集(从 pos 到 pos+31),包括 b 本身
        b = np.broadcast(b, *args[pos:(pos + 31)])
    # 返回广播后的数组的形状
    return b.shape
# 定义一个空的 NumPy 数据类型作为默认值
_size0_dtype = np.dtype([])


@set_module('numpy')
# 将输入的形状广播成单个形状。
def broadcast_shapes(*args):
    """
    Broadcast the input shapes into a single shape.

    :ref:`Learn more about broadcasting here <basics.broadcasting>`.

    .. versionadded:: 1.20.0

    Parameters
    ----------
    *args : tuples of ints, or ints
        The shapes to be broadcast against each other.

    Returns
    -------
    tuple
        Broadcasted shape.

    Raises
    ------
    ValueError
        If the shapes are not compatible and cannot be broadcast according
        to NumPy's broadcasting rules.

    See Also
    --------
    broadcast
    broadcast_arrays
    broadcast_to

    Examples
    --------
    >>> np.broadcast_shapes((1, 2), (3, 1), (3, 2))
    (3, 2)

    >>> np.broadcast_shapes((6, 7), (5, 6, 1), (7,), (5, 1, 7))
    (5, 6, 7)
    """
    # 创建一个包含指定形状的空数组列表,使用默认的空数据类型 _size0_dtype
    arrays = [np.empty(x, dtype=_size0_dtype) for x in args]
    # 调用内部函数 _broadcast_shape 对数组进行广播操作,并返回结果
    return _broadcast_shape(*arrays)


# 定义 _broadcast_arrays_dispatcher 函数,用于分发 broadcast_arrays 函数的参数
def _broadcast_arrays_dispatcher(*args, subok=None):
    return args


@array_function_dispatch(_broadcast_arrays_dispatcher, module='numpy')
# 广播任意数量的数组。
def broadcast_arrays(*args, subok=False):
    """
    Broadcast any number of arrays against each other.

    Parameters
    ----------
    *args : array_likes
        The arrays to broadcast.

    subok : bool, optional
        If True, then sub-classes will be passed-through, otherwise
        the returned arrays will be forced to be a base-class array (default).

    Returns
    -------
    broadcasted : tuple of arrays
        These arrays are views on the original arrays.  They are typically
        not contiguous.  Furthermore, more than one element of a
        broadcasted array may refer to a single memory location. If you need
        to write to the arrays, make copies first. While you can set the
        ``writable`` flag True, writing to a single output value may end up
        changing more than one location in the output array.

        .. deprecated:: 1.17
            The output is currently marked so that if written to, a deprecation
            warning will be emitted. A future version will set the
            ``writable`` flag False so writing to it will raise an error.

    See Also
    --------
    broadcast
    broadcast_to
    broadcast_shapes

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

    Here is a useful idiom for getting contiguous copies instead of
    non-contiguous views.

    >>> [np.array(a) for a in np.broadcast_arrays(x, y)]
    [array([[1, 2, 3],
            [1, 2, 3]]),
     array([[4, 4, 4],
            [5, 5, 5]])]

    """
    # nditer is not used here to avoid the limit of 32 arrays.
    # Otherwise, something like the following one-liner would suffice:
    # return np.nditer(args, flags=['multi_index', 'zerosize_ok'],
    #                  order='C').itviews
    # 列表推导式,对传入的每个参数进行处理,将其转换为 NumPy 数组
    args = [np.array(_m, copy=None, subok=subok) for _m in args]

    # 计算广播后的数组形状,_broadcast_shape 是一个自定义函数用于计算广播形状
    shape = _broadcast_shape(*args)

    # 列表推导式,对每个数组进行检查和处理:
    # 如果数组形状与广播后的形状相同,则保持不变
    # 否则,使用 _broadcast_to 函数将数组广播到指定形状
    result = [array if array.shape == shape
              else _broadcast_to(array, shape, subok=subok, readonly=False)
                              for array in args]
    # 返回结果元组,其中包含广播后的所有数组
    return tuple(result)

.\numpy\numpy\lib\_stride_tricks_impl.pyi

# 导入必要的模块和类型
from collections.abc import Iterable  # 导入 Iterable 抽象基类
from typing import Any, TypeVar, overload, SupportsIndex  # 导入类型注解相关模块

from numpy import generic  # 导入 numpy 的 generic 类型
from numpy._typing import (  # 导入 numpy 的类型注解
    NDArray,
    ArrayLike,
    _ShapeLike,
    _Shape,
    _ArrayLike
)

_SCT = TypeVar("_SCT", bound=generic)  # 定义一个泛型类型 _SCT,限定为 generic 的子类

__all__: list[str]  # 定义 __all__ 列表,用于模块导入时的限定符

class DummyArray:
    __array_interface__: dict[str, Any]  # 定义一个成员变量 __array_interface__,类型为字典[str, Any]
    base: None | NDArray[Any]  # 定义成员变量 base,可以是 None 或者 NDArray[Any] 类型

    def __init__(
        self,
        interface: dict[str, Any],
        base: None | NDArray[Any] = ...,
    ) -> None:
        ...  # DummyArray 类的初始化方法,接受一个字典和一个可选的 NDArray[Any] 参数

@overload
def as_strided(
    x: _ArrayLike[_SCT],
    shape: None | Iterable[int] = ...,
    strides: None | Iterable[int] = ...,
    subok: bool = ...,
    writeable: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def as_strided(
    x: ArrayLike,
    shape: None | Iterable[int] = ...,
    strides: None | Iterable[int] = ...,
    subok: bool = ...,
    writeable: bool = ...,
) -> NDArray[Any]: ...
# 函数重载定义:as_strided 函数可以接受不同类型的参数,返回相应的 NDArray

@overload
def sliding_window_view(
    x: _ArrayLike[_SCT],
    window_shape: int | Iterable[int],
    axis: None | SupportsIndex = ...,
    *,
    subok: bool = ...,
    writeable: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def sliding_window_view(
    x: ArrayLike,
    window_shape: int | Iterable[int],
    axis: None | SupportsIndex = ...,
    *,
    subok: bool = ...,
    writeable: bool = ...,
) -> NDArray[Any]: ...
# 函数重载定义:sliding_window_view 函数可以接受不同类型的参数,返回相应的 NDArray

@overload
def broadcast_to(
    array: _ArrayLike[_SCT],
    shape: int | Iterable[int],
    subok: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def broadcast_to(
    array: ArrayLike,
    shape: int | Iterable[int],
    subok: bool = ...,
) -> NDArray[Any]: ...
# 函数重载定义:broadcast_to 函数可以接受不同类型的参数,返回相应的 NDArray

def broadcast_shapes(*args: _ShapeLike) -> _Shape:
    ...  # broadcast_shapes 函数接受多个参数 _ShapeLike 类型,返回 _Shape 类型

def broadcast_arrays(
    *args: ArrayLike,
    subok: bool = ...,
) -> tuple[NDArray[Any], ...]:
    ...  # broadcast_arrays 函数接受多个 ArrayLike 类型的参数,返回一个元组,其中包含 NDArray[Any] 类型的数据

.\numpy\numpy\lib\_twodim_base_impl.py

""" Basic functions for manipulating 2d arrays

"""
# 导入 functools 模块,用于创建偏函数
import functools
# 导入 operator 模块,用于操作符函数
import operator

# 导入以下 numpy 内部模块和函数
from numpy._core._multiarray_umath import _array_converter
from numpy._core.numeric import (
    asanyarray, arange, zeros, greater_equal, multiply, ones,
    asarray, where, int8, int16, int32, int64, intp, empty, promote_types,
    diagonal, nonzero, indices
    )
# 导入 numpy 的 overrides 模块和函数
from numpy._core.overrides import set_array_function_like_doc, set_module
from numpy._core import overrides
# 导入 numpy 的 iinfo 模块
from numpy._core import iinfo
# 导入 numpy 的 _stride_tricks_impl 模块中的 broadcast_to 函数
from numpy.lib._stride_tricks_impl import broadcast_to


# 定义公开的函数和类列表
__all__ = [
    'diag', 'diagflat', 'eye', 'fliplr', 'flipud', 'tri', 'triu',
    'tril', 'vander', 'histogram2d', 'mask_indices', 'tril_indices',
    'tril_indices_from', 'triu_indices', 'triu_indices_from', ]


# 创建 functools.partial 对象,用于将 overrides.array_function_dispatch 函数与特定模块名 'numpy' 绑定
array_function_dispatch = functools.partial(
    overrides.array_function_dispatch, module='numpy')


# 获取 int8、int16 和 int32 类型的信息并存储在 i1、i2 和 i4 变量中
i1 = iinfo(int8)
i2 = iinfo(int16)
i4 = iinfo(int32)


def _min_int(low, high):
    """ get small int that fits the range """
    # 根据给定的范围返回适合的最小整数类型
    if high <= i1.max and low >= i1.min:
        return int8
    if high <= i2.max and low >= i2.min:
        return int16
    if high <= i4.max and low >= i4.min:
        return int32
    return int64


# 定义用于 fliplr 函数的分发器
def _flip_dispatcher(m):
    return (m,)


@array_function_dispatch(_flip_dispatcher)
def fliplr(m):
    """
    Reverse the order of elements along axis 1 (left/right).

    For a 2-D array, this flips the entries in each row in the left/right
    direction. Columns are preserved, but appear in a different order than
    before.

    Parameters
    ----------
    m : array_like
        Input array, must be at least 2-D.

    Returns
    -------
    f : ndarray
        A view of `m` with the columns reversed.  Since a view
        is returned, this operation is :math:`\\mathcal O(1)`.

    See Also
    --------
    flipud : Flip array in the up/down direction.
    flip : Flip array in one or more dimensions.
    rot90 : Rotate array counterclockwise.

    Notes
    -----
    Equivalent to ``m[:,::-1]`` or ``np.flip(m, axis=1)``.
    Requires the array to be at least 2-D.

    Examples
    --------
    >>> A = np.diag([1.,2.,3.])
    >>> A
    array([[1.,  0.,  0.],
           [0.,  2.,  0.],
           [0.,  0.,  3.]])
    >>> np.fliplr(A)
    array([[0.,  0.,  1.],
           [0.,  2.,  0.],
           [3.,  0.,  0.]])

    >>> rng = np.random.default_rng()
    >>> A = rng.normal(size=(2,3,5))
    >>> np.all(np.fliplr(A) == A[:,::-1,...])
    True

    """
    # 将输入 m 转换为 ndarray 类型
    m = asanyarray(m)
    # 如果 m 的维度小于 2,则引发 ValueError 异常
    if m.ndim < 2:
        raise ValueError("Input must be >= 2-d.")
    # 返回列反转后的 m 视图
    return m[:, ::-1]


@array_function_dispatch(_flip_dispatcher)
def flipud(m):
    """
    Reverse the order of elements along axis 0 (up/down).

    For a 2-D array, this flips the entries in each column in the up/down
    direction. Rows are preserved, but appear in a different order than before.

    Parameters
    ----------
    m : array_like
        Input array.

    Returns
    -------
    # 将输入的数组 m 转换为 numpy 数组,确保能够进行后续操作
    m = asanyarray(m)
    # 如果输入数组的维度小于 1,则抛出值错误异常
    if m.ndim < 1:
        raise ValueError("Input must be >= 1-d.")
    # 返回翻转行的视图数组,相当于 m[::-1, ...] 的操作
    return m[::-1, ...]
# 用于设置函数的数组功能文档样式
@set_array_function_like_doc
# 用于设置函数的模块为 'numpy'
@set_module('numpy')
# 定义一个名为 eye 的函数,生成一个二维数组,对角线为 1,其他位置为 0
def eye(N, M=None, k=0, dtype=float, order='C', *, device=None, like=None):
    """
    Return a 2-D array with ones on the diagonal and zeros elsewhere.

    Parameters
    ----------
    N : int
      Number of rows in the output.
    M : int, optional
      Number of columns in the output. If None, defaults to `N`.
    k : int, optional
      Index of the diagonal: 0 (the default) refers to the main diagonal,
      a positive value refers to an upper diagonal, and a negative value
      to a lower diagonal.
    dtype : data-type, optional
      Data-type of the returned array.
    order : {'C', 'F'}, optional
        Whether the output should be stored in row-major (C-style) or
        column-major (Fortran-style) order in memory.

        .. versionadded:: 1.14.0
    device : str, optional
        The device on which to place the created array. Default: None.
        For Array-API interoperability only, so must be ``"cpu"`` if passed.

        .. versionadded:: 2.0.0
    ${ARRAY_FUNCTION_LIKE}

        .. versionadded:: 1.20.0

    Returns
    -------
    I : ndarray of shape (N,M)
      An array where all elements are equal to zero, except for the `k`-th
      diagonal, whose values are equal to one.

    See Also
    --------
    identity : (almost) equivalent function
    diag : diagonal 2-D array from a 1-D array specified by the user.

    Examples
    --------
    >>> np.eye(2, dtype=int)
    array([[1, 0],
           [0, 1]])
    >>> np.eye(3, k=1)
    array([[0.,  1.,  0.],
           [0.,  0.,  1.],
           [0.,  0.,  0.]])

    """
    # 如果 like 参数不为 None,则调用 _eye_with_like 函数处理
    if like is not None:
        return _eye_with_like(
            like, N, M=M, k=k, dtype=dtype, order=order, device=device
        )
    # 如果 M 为 None,则将 M 设为 N
    if M is None:
        M = N
    # 创建一个形状为 (N, M) 的零数组 m,数据类型为 dtype,存储顺序为 order,设备为 device
    m = zeros((N, M), dtype=dtype, order=order, device=device)
    # 如果 k 大于等于 M,则直接返回 m
    if k >= M:
        return m
    # 确保 M 和 k 是整数,以避免意外的类型转换结果
    M = operator.index(M)
    k = operator.index(k)
    # 如果 k 大于等于 0,则将 i 设为 k;否则将 i 设为 (-k) * M
    if k >= 0:
        i = k
    else:
        i = (-k) * M
    # 在 m 的前 M-k 行中,每隔 M+1 个元素设置为 1,从索引 i 开始
    m[:M-k].flat[i::M+1] = 1
    # 返回生成的二维数组 m
    return m


# 通过数组函数分发装饰器将 _eye_with_like 函数与 eye 函数关联起来
_eye_with_like = array_function_dispatch()(eye)


# 定义一个 _diag_dispatcher 函数,用于 diag 函数的分派
def _diag_dispatcher(v, k=None):
    return (v,)


# 通过数组函数分发装饰器将 _diag_dispatcher 函数与 diag 函数关联起来
@array_function_dispatch(_diag_dispatcher)
# 定义 diag 函数,用于提取对角线或构造对角线数组
def diag(v, k=0):
    """
    Extract a diagonal or construct a diagonal array.

    See the more detailed documentation for ``numpy.diagonal`` if you use this
    function to extract a diagonal and wish to write to the resulting array;
    whether it returns a copy or a view depends on what version of numpy you
    are using.

    Parameters
    ----------
    v : array_like
        If `v` is a 2-D array, return a copy of its `k`-th diagonal.
        If `v` is a 1-D array, return a 2-D array with `v` on the `k`-th
        diagonal.

    """
    v = asanyarray(v)
    s = v.shape
    # 将输入转换为任意数组,确保可以处理不同类型的输入
    if len(s) == 1:
        # 如果输入是一维数组
        n = s[0]+abs(k)
        # 计算输出数组的大小,包括需要的额外对角线长度
        res = zeros((n, n), v.dtype)
        # 创建一个全零数组作为输出,与输入数组类型相同
        if k >= 0:
            i = k
        else:
            i = (-k) * n
        # 计算对角线的起始索引
        res[:n-k].flat[i::n+1] = v
        # 将输入数组的值填充到输出数组的对角线上
        return res
    elif len(s) == 2:
        # 如果输入是二维数组
        return diagonal(v, k)
        # 调用 diagonal 函数返回指定位置的对角线数组
    else:
        # 处理不支持的输入维度
        raise ValueError("Input must be 1- or 2-d.")
        # 抛出值错误,要求输入必须是一维或二维数组
@array_function_dispatch(_diag_dispatcher)
# 使用装饰器将 _diag_dispatcher 函数与 diagflat 函数关联,用于数组函数分发
def diagflat(v, k=0):
    """
    Create a two-dimensional array with the flattened input as a diagonal.

    Parameters
    ----------
    v : array_like
        Input data, which is flattened and set as the `k`-th
        diagonal of the output.
    k : int, optional
        Diagonal to set; 0, the default, corresponds to the "main" diagonal,
        a positive (negative) `k` giving the number of the diagonal above
        (below) the main.

    Returns
    -------
    out : ndarray
        The 2-D output array.

    See Also
    --------
    diag : MATLAB work-alike for 1-D and 2-D arrays.
    diagonal : Return specified diagonals.
    trace : Sum along diagonals.

    Examples
    --------
    >>> np.diagflat([[1,2], [3,4]])
    array([[1, 0, 0, 0],
           [0, 2, 0, 0],
           [0, 0, 3, 0],
           [0, 0, 0, 4]])

    >>> np.diagflat([1,2], 1)
    array([[0, 1, 0],
           [0, 0, 2],
           [0, 0, 0]])

    """
    # 转换输入数据 v 并展平
    conv = _array_converter(v)
    v, = conv.as_arrays(subok=False)
    v = v.ravel()
    s = len(v)
    n = s + abs(k)
    # 创建一个形状为 (n, n) 的零数组,指定数据类型为 v 的数据类型
    res = zeros((n, n), v.dtype)
    if (k >= 0):
        # 对于 k >= 0 的情况,设置正对角线及其上的对角线
        i = arange(0, n-k, dtype=intp)
        fi = i+k+i*n
    else:
        # 对于 k < 0 的情况,设置负对角线及其下的对角线
        i = arange(0, n+k, dtype=intp)
        fi = i+(i-k)*n
    # 将展平的 v 数组数据设置到 res 的指定位置
    res.flat[fi] = v

    return conv.wrap(res)


@set_array_function_like_doc
@set_module('numpy')
# 使用装饰器设置 tri 函数的数组函数行为及所属模块为 numpy
def tri(N, M=None, k=0, dtype=float, *, like=None):
    """
    An array with ones at and below the given diagonal and zeros elsewhere.

    Parameters
    ----------
    N : int
        Number of rows in the array.
    M : int, optional
        Number of columns in the array.
        By default, `M` is taken equal to `N`.
    k : int, optional
        The sub-diagonal at and below which the array is filled.
        `k` = 0 is the main diagonal, while `k` < 0 is below it,
        and `k` > 0 is above.  The default is 0.
    dtype : dtype, optional
        Data type of the returned array.  The default is float.
    ${ARRAY_FUNCTION_LIKE}

        .. versionadded:: 1.20.0

    Returns
    -------
    tri : ndarray of shape (N, M)
        Array with its lower triangle filled with ones and zero elsewhere;
        in other words ``T[i,j] == 1`` for ``j <= i + k``, 0 otherwise.

    Examples
    --------
    >>> np.tri(3, 5, 2, dtype=int)
    array([[1, 1, 1, 0, 0],
           [1, 1, 1, 1, 0],
           [1, 1, 1, 1, 1]])

    >>> np.tri(3, 5, -1)
    array([[0.,  0.,  0.,  0.,  0.],
           [1.,  0.,  0.,  0.,  0.],
           [1.,  1.,  0.,  0.,  0.]])

    """
    if like is not None:
        # 如果指定了 like 参数,返回与 like 相同类型的三角矩阵
        return _tri_with_like(like, N, M=M, k=k, dtype=dtype)

    if M is None:
        M = N

    # 创建一个布尔类型的 N x M 形状的矩阵,其中下三角(包括对角线)为 1,其余为 0
    m = greater_equal.outer(arange(N, dtype=_min_int(0, N)),
                            arange(-k, M-k, dtype=_min_int(-k, M - k)))

    # 避免在已经是布尔类型时复制矩阵
    m = m.astype(dtype, copy=False)

    return m


# 将 array_function_dispatch 装饰器应用到 tri 函数
_tri_with_like = array_function_dispatch()(tri)
# 根据输入参数生成一个 Vandermonde 矩阵
def vander(x, N=None, increasing=False):
    # 如果 N 为 None,则设置 N 为 x 的长度
    if N is None:
        N = len(x)
    # 根据 increasing 参数决定是否递增排序
    if increasing:
        # 生成递增排序的 Vandermonde 矩阵
        return array([x**(N-1-i) for i in range(N)]).T
    else:
        # 生成递减排序的 Vandermonde 矩阵
        return array([x**i for i in range(N)]).T
    """
    The columns of the output matrix are powers of the input vector. The
    order of the powers is determined by the `increasing` boolean argument.
    Specifically, when `increasing` is False, the `i`-th output column is
    the input vector raised element-wise to the power of ``N - i - 1``. Such
    a matrix with a geometric progression in each row is named for Alexandre-
    Theophile Vandermonde.
    
    Parameters
    ----------
    x : array_like
        1-D input array.
    N : int, optional
        Number of columns in the output.  If `N` is not specified, a square
        array is returned (``N = len(x)``).
    increasing : bool, optional
        Order of the powers of the columns.  If True, the powers increase
        from left to right, if False (the default) they are reversed.
    
        .. versionadded:: 1.9.0
    
    Returns
    -------
    out : ndarray
        Vandermonde matrix.  If `increasing` is False, the first column is
        ``x^(N-1)``, the second ``x^(N-2)`` and so forth. If `increasing` is
        True, the columns are ``x^0, x^1, ..., x^(N-1)``.
    
    See Also
    --------
    polynomial.polynomial.polyvander
    
    Examples
    --------
    >>> x = np.array([1, 2, 3, 5])
    >>> N = 3
    >>> np.vander(x, N)
    array([[ 1,  1,  1],
           [ 4,  2,  1],
           [ 9,  3,  1],
           [25,  5,  1]])
    
    >>> np.column_stack([x**(N-1-i) for i in range(N)])
    array([[ 1,  1,  1],
           [ 4,  2,  1],
           [ 9,  3,  1],
           [25,  5,  1]])
    
    >>> x = np.array([1, 2, 3, 5])
    >>> np.vander(x)
    array([[  1,   1,   1,   1],
           [  8,   4,   2,   1],
           [ 27,   9,   3,   1],
           [125,  25,   5,   1]])
    >>> np.vander(x, increasing=True)
    array([[  1,   1,   1,   1],
           [  1,   2,   4,   8],
           [  1,   3,   9,  27],
           [  1,   5,  25, 125]])
    
    The determinant of a square Vandermonde matrix is the product
    of the differences between the values of the input vector:
    
    >>> np.linalg.det(np.vander(x))
    48.000000000000043 # may vary
    >>> (5-3)*(5-2)*(5-1)*(3-2)*(3-1)*(2-1)
    48
    """
    
    # 将输入数组 x 转换为 ndarray 类型
    x = asarray(x)
    
    # 如果 x 不是一维数组,则抛出异常
    if x.ndim != 1:
        raise ValueError("x must be a one-dimensional array or sequence.")
    
    # 如果未指定 N,则将 N 设置为 x 的长度
    if N is None:
        N = len(x)
    
    # 创建一个空的数组 v,形状为 (len(x), N),数据类型为 x 的数据类型和整数类型的广播类型
    v = empty((len(x), N), dtype=promote_types(x.dtype, int))
    
    # 根据 increasing 参数选择操作数组 tmp
    tmp = v[:, ::-1] if not increasing else v
    
    # 如果 N > 0,则将 tmp 的第一列设置为 1
    if N > 0:
        tmp[:, 0] = 1
    
    # 如果 N > 1,则将 tmp 的第二列到最后一列设置为 x 的列向量的累积乘积
    if N > 1:
        tmp[:, 1:] = x[:, None]
        multiply.accumulate(tmp[:, 1:], out=tmp[:, 1:], axis=1)
    
    # 返回生成的 Vandermonde 矩阵 v
    return v
def _histogram2d_dispatcher(x, y, bins=None, range=None, density=None,
                            weights=None):
    # 生成器函数,用于分派参数 x, y, bins, range, density, weights
    yield x  # 生成器返回 x
    yield y  # 生成器返回 y

    # 以下逻辑从 histogram2d 中的检查逻辑进行了糟糕的适应
    try:
        N = len(bins)  # 尝试获取 bins 的长度
    except TypeError:
        N = 1  # 如果无法获取长度,则默认 N 为 1
    if N == 2:
        yield from bins  # 如果 N 等于 2,则返回 bins 中的元素 [x, y]
    else:
        yield bins  # 否则返回 bins

    yield weights  # 返回 weights


@array_function_dispatch(_histogram2d_dispatcher)
def histogram2d(x, y, bins=10, range=None, density=None, weights=None):
    """
    Compute the bi-dimensional histogram of two data samples.

    Parameters
    ----------
    x : array_like, shape (N,)
        An array containing the x coordinates of the points to be
        histogrammed.
    y : array_like, shape (N,)
        An array containing the y coordinates of the points to be
        histogrammed.
    bins : int or array_like or [int, int] or [array, array], optional
        The bin specification:

        * If int, the number of bins for the two dimensions (nx=ny=bins).
        * If array_like, the bin edges for the two dimensions
          (x_edges=y_edges=bins).
        * If [int, int], the number of bins in each dimension
          (nx, ny = bins).
        * If [array, array], the bin edges in each dimension
          (x_edges, y_edges = bins).
        * A combination [int, array] or [array, int], where int
          is the number of bins and array is the bin edges.

    range : array_like, shape(2,2), optional
        The leftmost and rightmost edges of the bins along each dimension
        (if not specified explicitly in the `bins` parameters):
        ``[[xmin, xmax], [ymin, ymax]]``. All values outside of this range
        will be considered outliers and not tallied in the histogram.
    density : bool, optional
        If False, the default, returns the number of samples in each bin.
        If True, returns the probability *density* function at the bin,
        ``bin_count / sample_count / bin_area``.
    weights : array_like, shape(N,), optional
        An array of values ``w_i`` weighing each sample ``(x_i, y_i)``.
        Weights are normalized to 1 if `density` is True. If `density` is
        False, the values of the returned histogram are equal to the sum of
        the weights belonging to the samples falling into each bin.

    Returns
    -------
    H : ndarray, shape(nx, ny)
        The bi-dimensional histogram of samples `x` and `y`. Values in `x`
        are histogrammed along the first dimension and values in `y` are
        histogrammed along the second dimension.
    xedges : ndarray, shape(nx+1,)
        The bin edges along the first dimension.
    yedges : ndarray, shape(ny+1,)
        The bin edges along the second dimension.

    See Also
    --------
    histogram : 1D histogram
    histogramdd : Multidimensional histogram

    Notes
    -----
    When `density` is True, then the returned histogram is the sample
    density, defined such that the sum over bins of the product
    """
    pass  # 空函数体,因为函数文档字符串已经提供了函数功能的说明
    # `bin_value * bin_area` is 1.
    # 上述表达式中 `bin_value * bin_area` 的结果为1。

    # Please note that the histogram does not follow the Cartesian convention
    # where `x` values are on the abscissa and `y` values on the ordinate
    # axis.  Rather, `x` is histogrammed along the first dimension of the
    # array (vertical), and `y` along the second dimension of the array
    # (horizontal).  This ensures compatibility with `histogramdd`.
    # 请注意,直方图不遵循笛卡尔坐标系的传统规定,其中 `x` 值位于横坐标轴上,
    # `y` 值位于纵坐标轴上。相反,`x` 被直方图化沿着数组的第一个维度(垂直方向),
    # `y` 被直方图化沿着数组的第二个维度(水平方向)。这样做确保与 `histogramdd` 兼容。

    # Examples
    # --------
    # 例子

    # Import necessary modules
    # 导入必要的模块
    >>> from matplotlib.image import NonUniformImage
    >>> import matplotlib.pyplot as plt

    # Construct a 2-D histogram with variable bin width. First define the bin
    # edges:
    # 构建一个具有可变箱宽的二维直方图。首先定义箱子的边缘:

    >>> xedges = [0, 1, 3, 5]
    >>> yedges = [0, 2, 3, 4, 6]

    # Next we create a histogram H with random bin content:
    # 接下来,我们用随机箱内容创建直方图 H:

    >>> x = np.random.normal(2, 1, 100)
    >>> y = np.random.normal(1, 1, 100)
    >>> H, xedges, yedges = np.histogram2d(x, y, bins=(xedges, yedges))

    # Histogram does not follow Cartesian convention (see Notes),
    # therefore transpose H for visualization purposes.
    # 直方图不遵循笛卡尔坐标系的传统规定(见注释),因此为了可视化目的转置 H。
    >>> H = H.T

    # :func:`imshow <matplotlib.pyplot.imshow>` can only display square bins:
    # :func:`imshow <matplotlib.pyplot.imshow>` 只能显示正方形的箱子:

    >>> fig = plt.figure(figsize=(7, 3))
    >>> ax = fig.add_subplot(131, title='imshow: square bins')
    >>> plt.imshow(H, interpolation='nearest', origin='lower',
    ...         extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])

    # :func:`pcolormesh <matplotlib.pyplot.pcolormesh>` can display actual edges:
    # :func:`pcolormesh <matplotlib.pyplot.pcolormesh>` 可以显示实际的边缘:

    >>> ax = fig.add_subplot(132, title='pcolormesh: actual edges',
    ...         aspect='equal')
    >>> X, Y = np.meshgrid(xedges, yedges)
    >>> ax.pcolormesh(X, Y, H)

    # :class:`NonUniformImage <matplotlib.image.NonUniformImage>` can be used to
    # display actual bin edges with interpolation:
    # :class:`NonUniformImage <matplotlib.image.NonUniformImage>` 可以用来显示带插值的实际箱边缘:

    >>> ax = fig.add_subplot(133, title='NonUniformImage: interpolated',
    ...         aspect='equal', xlim=xedges[[0, -1]], ylim=yedges[[0, -1]])
    >>> im = NonUniformImage(ax, interpolation='bilinear')
    >>> xcenters = (xedges[:-1] + xedges[1:]) / 2
    >>> ycenters = (yedges[:-1] + yedges[1:]) / 2
    >>> im.set_data(xcenters, ycenters, H)
    >>> ax.add_image(im)

    # Show the plot
    # 显示图形
    >>> plt.show()

    # It is also possible to construct a 2-D histogram without specifying bin
    # edges:
    # 也可以构建一个没有指定箱边界的二维直方图:

    >>> # Generate non-symmetric test data
    >>> n = 10000
    >>> x = np.linspace(1, 100, n)
    >>> y = 2*np.log(x) + np.random.rand(n) - 0.5
    >>> # Compute 2d histogram. Note the order of x/y and xedges/yedges
    >>> H, yedges, xedges = np.histogram2d(y, x, bins=20)

    # Now we can plot the histogram using
    # :func:`pcolormesh <matplotlib.pyplot.pcolormesh>`, and a
    # :func:`hexbin <matplotlib.pyplot.hexbin>` for comparison.
    # 现在我们可以使用 :func:`pcolormesh <matplotlib.pyplot.pcolormesh>` 绘制直方图,
    # 并使用 :func:`hexbin <matplotlib.pyplot.hexbin>` 进行比较。

    >>> # Plot histogram using pcolormesh
    >>> fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)
    >>> ax1.pcolormesh(xedges, yedges, H, cmap='rainbow')
    >>> ax1.plot(x, 2*np.log(x), 'k-')
    >>> ax1.set_xlim(x.min(), x.max())
    >>> ax1.set_ylim(y.min(), y.max())
    >>> ax1.set_xlabel('x')
    >>> ax1.set_ylabel('y')
    >>> ax1.set_title('histogram2d')
    >>> ax1.grid()

    >>> # 在 ax1 上创建二维直方图
    >>> # 设置 y 轴的范围为 y 的最小值到最大值
    >>> ax1.set_ylim(y.min(), y.max())
    >>> # 设置 x 轴标签为 'x'
    >>> ax1.set_xlabel('x')
    >>> # 设置 y 轴标签为 'y'
    >>> ax1.set_ylabel('y')
    >>> # 设置图表标题为 'histogram2d'
    >>> ax1.set_title('histogram2d')
    >>> # 在 ax1 上显示网格线
    >>> ax1.grid()

    >>> # 在 ax2 上创建 hexbin 图进行比较
    >>> ax2.hexbin(x, y, gridsize=20, cmap='rainbow')
    >>> # 绘制直线图,x 为自变量,2*np.log(x) 为因变量,线条为黑色实线
    >>> ax2.plot(x, 2*np.log(x), 'k-')
    >>> # 设置 ax2 的标题为 'hexbin'
    >>> ax2.set_title('hexbin')
    >>> # 设置 x 轴的范围为 x 的最小值到最大值
    >>> ax2.set_xlim(x.min(), x.max())
    >>> # 设置 x 轴标签为 'x'
    >>> ax2.set_xlabel('x')
    >>> # 在 ax2 上显示网格线
    >>> ax2.grid()

    >>> # 显示整个图形
    >>> plt.show()
    """
    from numpy import histogramdd

    # 检查 x 和 y 的长度是否相等,如果不相等则抛出 ValueError 异常
    if len(x) != len(y):
        raise ValueError('x and y must have the same length.')

    # 尝试获取 bins 的长度 N,如果 bins 不是一个数组则 N 为 1
    try:
        N = len(bins)
    except TypeError:
        N = 1

    # 如果 N 不是 1 也不是 2,则将 bins 转换为数组,并分别设置 xedges 和 yedges
    if N != 1 and N != 2:
        xedges = yedges = asarray(bins)
        bins = [xedges, yedges]
    
    # 计算二维直方图 hist 和对应的边界 edges
    hist, edges = histogramdd([x, y], bins, range, density, weights)
    # 返回直方图 hist,以及 x 和 y 的边界 edges[0] 和 edges[1]
    return hist, edges[0], edges[1]
# 设置模块为 'numpy',这是一个装饰器,用于指定模块名称
@set_module('numpy')
# 定义函数 mask_indices,返回用于访问 (n, n) 数组的索引,基于给定的遮罩函数
def mask_indices(n, mask_func, k=0):
    """
    Return the indices to access (n, n) arrays, given a masking function.

    Assume `mask_func` is a function that, for a square array a of size
    ``(n, n)`` with a possible offset argument `k`, when called as
    ``mask_func(a, k)`` returns a new array with zeros in certain locations
    (functions like `triu` or `tril` do precisely this). Then this function
    returns the indices where the non-zero values would be located.

    Parameters
    ----------
    n : int
        The returned indices will be valid to access arrays of shape (n, n).
    mask_func : callable
        A function whose call signature is similar to that of `triu`, `tril`.
        That is, ``mask_func(x, k)`` returns a boolean array, shaped like `x`.
        `k` is an optional argument to the function.
    k : scalar
        An optional argument which is passed through to `mask_func`. Functions
        like `triu`, `tril` take a second argument that is interpreted as an
        offset.

    Returns
    -------
    indices : tuple of arrays.
        The `n` arrays of indices corresponding to the locations where
        ``mask_func(np.ones((n, n)), k)`` is True.

    See Also
    --------
    triu, tril, triu_indices, tril_indices

    Notes
    -----
    .. versionadded:: 1.4.0

    Examples
    --------
    These are the indices that would allow you to access the upper triangular
    part of any 3x3 array:

    >>> iu = np.mask_indices(3, np.triu)

    For example, if `a` is a 3x3 array:

    >>> a = np.arange(9).reshape(3, 3)
    >>> a
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    >>> a[iu]
    array([0, 1, 2, 4, 5, 8])

    An offset can be passed also to the masking function.  This gets us the
    indices starting on the first diagonal right of the main one:

    >>> iu1 = np.mask_indices(3, np.triu, 1)

    with which we now extract only three elements:

    >>> a[iu1]
    array([1, 2, 5])

    """
    # 创建一个大小为 (n, n) 的整数数组 m,所有元素为 1
    m = ones((n, n), int)
    # 调用 mask_func 函数,传入 m 和 k,返回一个布尔数组 a
    a = mask_func(m, k)
    # 返回 a 中非零元素的索引
    return nonzero(a != 0)


# 设置模块为 'numpy',这是一个装饰器,用于指定模块名称
@set_module('numpy')
# 定义函数 tril_indices,返回一个 (n, m) 数组的下三角形部分的索引
def tril_indices(n, k=0, m=None):
    """
    Return the indices for the lower-triangle of an (n, m) array.

    Parameters
    ----------
    n : int
        The row dimension of the arrays for which the returned
        indices will be valid.
    k : int, optional
        Diagonal offset (see `tril` for details).
    m : int, optional
        .. versionadded:: 1.9.0

        The column dimension of the arrays for which the returned
        arrays will be valid.
        By default `m` is taken equal to `n`.

    Returns
    -------
    inds : tuple of arrays
        The indices for the triangle. The returned tuple contains two arrays,
        each with the indices along one dimension of the array.

    See also
    --------
    triu_indices : similar function, for upper-triangular.
    mask_indices : generic function accepting an arbitrary mask function.
    tril, triu

    Notes

    """
    # 根据文档,该函数是在 NumPy 1.4.0 版本中添加的新功能
    .. versionadded:: 1.4.0
    
    # 示例部分,展示如何计算两种不同的索引集合,用于访问4x4数组:
    # 一种是从主对角线开始的下三角部分,另一种是从右侧两个对角线开始。
    
    # 使用 np.tril_indices 函数计算出4x4数组的下三角部分的索引集合
    il1 = np.tril_indices(4)
    
    # 使用 np.tril_indices 函数计算出4x4数组中右侧两个对角线开始的索引集合
    il2 = np.tril_indices(4, 2)
    
    # 下面展示了如何将这些索引集合应用到示例数组 a 上:
    
    # 示例数组 a,形状为4x4
    a = np.arange(16).reshape(4, 4)
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    
    # 使用 il1 索引集合进行索引:
    >>> a[il1]
    array([ 0,  4,  5,  8,  9, 10, 12, 13, 14, 15])
    
    # 使用 il1 索引集合进行赋值:
    >>> a[il1] = -1
    >>> a
    array([[-1,  1,  2,  3],
           [-1, -1,  6,  7],
           [-1, -1, -1, 11],
           [-1, -1, -1, -1]])
    
    # 使用 il2 索引集合进行赋值,涵盖几乎整个数组(从主对角线右侧两个对角线开始):
    >>> a[il2] = -10
    >>> a
    array([[-10, -10, -10,   3],
           [-10, -10, -10, -10],
           [-10, -10, -10, -10],
           [-10, -10, -10, -10]])
    
    """
    tri_ = tri(n, m, k=k, dtype=bool)
    
    # 返回一个元组,其中每个元素是根据布尔数组 tri_ 的形状广播后的 inds 的值
    return tuple(broadcast_to(inds, tri_.shape)[tri_]
                 for inds in indices(tri_.shape, sparse=True))
# 定义一个函数分派器,返回输入参数的元组
def _trilu_indices_form_dispatcher(arr, k=None):
    return (arr,)


# 使用装饰器将下面的函数注册到数组函数分派机制中
@array_function_dispatch(_trilu_indices_form_dispatcher)
# 定义函数 tril_indices_from,返回给定数组的下三角部分的索引
def tril_indices_from(arr, k=0):
    """
    返回数组的下三角部分的索引。

    查看 `tril_indices` 获取详细信息。

    Parameters
    ----------
    arr : array_like
        索引适用于维度与 arr 相同的方形数组。
    k : int, optional
        对角线偏移量(详见 `tril` 的说明)。

    Examples
    --------

    创建一个 4x4 的数组。

    >>> a = np.arange(16).reshape(4, 4)
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])

    将数组传递给函数以获取下三角元素的索引。

    >>> trili = np.tril_indices_from(a)
    >>> trili
    (array([0, 1, 1, 2, 2, 2, 3, 3, 3, 3]), array([0, 0, 1, 0, 1, 2, 0, 1, 2, 3]))

    >>> a[trili]
    array([ 0,  4,  5,  8,  9, 10, 12, 13, 14, 15])

    这是 `tril_indices()` 的语法糖。

    >>> np.tril_indices(a.shape[0])
    (array([0, 1, 1, 2, 2, 2, 3, 3, 3, 3]), array([0, 0, 1, 0, 1, 2, 0, 1, 2, 3]))

    使用 `k` 参数来返回到第 k 条对角线的下三角数组的索引。

    >>> trili1 = np.tril_indices_from(a, k=1)
    >>> a[trili1]
    array([ 0,  1,  4,  5,  6,  8,  9, 10, 11, 12, 13, 14, 15])

    See Also
    --------
    tril_indices, tril, triu_indices_from

    Notes
    -----
    .. versionadded:: 1.4.0

    """
    # 如果输入数组不是二维的,抛出 ValueError 异常
    if arr.ndim != 2:
        raise ValueError("input array must be 2-d")
    # 返回调用 tril_indices 函数得到的结果,指定数组的行数和列数以及对角线偏移量
    return tril_indices(arr.shape[-2], k=k, m=arr.shape[-1])


# 将下面的函数设置为 numpy 模块的一部分
@set_module('numpy')
# 定义 triu_indices 函数,返回一个 (n, m) 数组的上三角部分的索引
def triu_indices(n, k=0, m=None):
    """
    返回一个 (n, m) 数组的上三角部分的索引。

    Parameters
    ----------
    n : int
        返回的索引适用于数组的大小。
    k : int, optional
        对角线偏移量(详见 `triu` 的说明)。
    m : int, optional
        .. versionadded:: 1.9.0

        返回的数组的列维度。
        默认情况下,`m` 等于 `n`。

    Returns
    -------
    inds : tuple, shape(2) of ndarrays, shape(`n`)
        三角形的索引。返回的元组包含两个数组,每个数组沿数组的一个维度包含索引。可用于切片形状为 (`n`, `n`) 的 ndarray。

    See also
    --------
    tril_indices : 类似的函数,用于下三角。
    mask_indices : 接受任意掩码函数的通用函数。
    triu, tril

    Notes
    -----
    .. versionadded:: 1.4.0

    Examples
    --------
    计算两组不同的索引以访问 4x4 数组,一组从主对角线开始为上三角部分,另一组从右边开始两个对角线更远的地方:

    >>> iu1 = np.triu_indices(4)
    >>> iu2 = np.triu_indices(4, 2)

    """
    # 此处省略函数主体,因为它只包含了文档字符串和一些函数签名,没有实际的代码实现
    # 创建一个布尔类型的三角形掩码,表示矩阵中不同的三角形区域
    tri_ = ~tri(n, m, k=k - 1, dtype=bool)

    # 返回一个元组,包含通过广播和掩码选择的索引的稀疏矩阵中的元素
    return tuple(broadcast_to(inds, tri_.shape)[tri_]
                 for inds in indices(tri_.shape, sparse=True))
# 使用装饰器来分派函数,根据数组的形式调度
@array_function_dispatch(_trilu_indices_form_dispatcher)
# 定义一个函数,返回给定数组的上三角部分的索引
def triu_indices_from(arr, k=0):
    """
    Return the indices for the upper-triangle of arr.

    See `triu_indices` for full details.

    Parameters
    ----------
    arr : ndarray, shape(N, N)
        The indices will be valid for square arrays.
        输入数组,应为方形数组,返回的索引对其有效。
    k : int, optional
        Diagonal offset (see `triu` for details).
        对角线的偏移量(参见 `triu` 以了解详情)。

    Returns
    -------
    triu_indices_from : tuple, shape(2) of ndarray, shape(N)
        Indices for the upper-triangle of `arr`.
        返回数组 `arr` 上三角部分的索引。

    Examples
    --------

    Create a 4 by 4 array.

    >>> a = np.arange(16).reshape(4, 4)
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])

    Pass the array to get the indices of the upper triangular elements.

    >>> triui = np.triu_indices_from(a)
    >>> triui
    (array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3]), array([0, 1, 2, 3, 1, 2, 3, 2, 3, 3]))

    >>> a[triui]
    array([ 0,  1,  2,  3,  5,  6,  7, 10, 11, 15])

    This is syntactic sugar for triu_indices().

    >>> np.triu_indices(a.shape[0])
    (array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3]), array([0, 1, 2, 3, 1, 2, 3, 2, 3, 3]))

    Use the `k` parameter to return the indices for the upper triangular array
    from the k-th diagonal.

    >>> triuim1 = np.triu_indices_from(a, k=1)
    >>> a[triuim1]
    array([ 1,  2,  3,  6,  7, 11])


    See Also
    --------
    triu_indices, triu, tril_indices_from

    Notes
    -----
    .. versionadded:: 1.4.0

    """
    # 如果输入数组的维度不是2,抛出值错误
    if arr.ndim != 2:
        raise ValueError("input array must be 2-d")
    # 返回调用 triu_indices 函数得到的结果,传递给它数组的形状及 k 参数
    return triu_indices(arr.shape[-2], k=k, m=arr.shape[-1])

.\numpy\numpy\lib\_twodim_base_impl.pyi

# 导入内建模块和函数
import builtins
# 导入抽象基类中的可调用对象和序列
from collections.abc import Callable, Sequence
# 导入类型提示
from typing import (
    Any,
    overload,
    TypeVar,
    Literal as L,
)

# 导入 NumPy 库,并导入一系列特定的数据类型和函数
import numpy as np
from numpy import (
    generic,
    number,
    timedelta64,
    datetime64,
    int_,
    intp,
    float64,
    signedinteger,
    floating,
    complexfloating,
    object_,
    _OrderCF,
)

# 导入 NumPy 内部的类型定义
from numpy._typing import (
    DTypeLike,
    _DTypeLike,
    ArrayLike,
    _ArrayLike,
    NDArray,
    _SupportsArrayFunc,
    _ArrayLikeInt_co,
    _ArrayLikeFloat_co,
    _ArrayLikeComplex_co,
    _ArrayLikeObject_co,
)

# 定义类型变量 _T 和 _SCT
_T = TypeVar("_T")
_SCT = TypeVar("_SCT", bound=generic)

# 定义回调函数类型 _MaskFunc,接受一个整数类型的 NumPy 数组和一个泛型参数,返回一个与 np.equal 兼容的数据类型数组
_MaskFunc = Callable[
    [NDArray[int_], _T],
    NDArray[number[Any] | np.bool | timedelta64 | datetime64 | object_],
]

# 定义模块的导出列表
__all__: list[str]

# 函数装饰器 @overload,用于指定函数的重载形式

# 函数 fliplr 的第一个重载形式,接受 _ArrayLike 类型参数 m,返回 _SCT 类型的 NumPy 数组
@overload
def fliplr(m: _ArrayLike[_SCT]) -> NDArray[_SCT]: ...

# 函数 fliplr 的第二个重载形式,接受 ArrayLike 类型参数 m,返回任意类型的 NumPy 数组
@overload
def fliplr(m: ArrayLike) -> NDArray[Any]: ...

# 函数 flipud 的第一个重载形式,接受 _ArrayLike 类型参数 m,返回 _SCT 类型的 NumPy 数组
@overload
def flipud(m: _ArrayLike[_SCT]) -> NDArray[_SCT]: ...

# 函数 flipud 的第二个重载形式,接受 ArrayLike 类型参数 m,返回任意类型的 NumPy 数组
@overload
def flipud(m: ArrayLike) -> NDArray[Any]: ...

# 函数 eye 的第一个重载形式,返回 float64 类型的 NumPy 数组
@overload
def eye(
    N: int,
    M: None | int = ...,
    k: int = ...,
    dtype: None = ...,
    order: _OrderCF = ...,
    *,
    device: None | L["cpu"] = ...,
    like: None | _SupportsArrayFunc = ...,
) -> NDArray[float64]: ...

# 函数 eye 的第二个重载形式,返回 _SCT 类型的 NumPy 数组
@overload
def eye(
    N: int,
    M: None | int = ...,
    k: int = ...,
    dtype: _DTypeLike[_SCT] = ...,
    order: _OrderCF = ...,
    *,
    device: None | L["cpu"] = ...,
    like: None | _SupportsArrayFunc = ...,
) -> NDArray[_SCT]: ...

# 函数 eye 的第三个重载形式,返回任意类型的 NumPy 数组
@overload
def eye(
    N: int,
    M: None | int = ...,
    k: int = ...,
    dtype: DTypeLike = ...,
    order: _OrderCF = ...,
    *,
    device: None | L["cpu"] = ...,
    like: None | _SupportsArrayFunc = ...,
) -> NDArray[Any]: ...

# 函数 diag 的第一个重载形式,接受 _ArrayLike 类型参数 v,返回 _SCT 类型的 NumPy 数组
@overload
def diag(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...

# 函数 diag 的第二个重载形式,接受 ArrayLike 类型参数 v,返回任意类型的 NumPy 数组
@overload
def diag(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...

# 函数 diagflat 的第一个重载形式,接受 _ArrayLike 类型参数 v,返回 _SCT 类型的 NumPy 数组
@overload
def diagflat(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...

# 函数 diagflat 的第二个重载形式,接受 ArrayLike 类型参数 v,返回任意类型的 NumPy 数组
@overload
def diagflat(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...

# 函数 tri 的第一个重载形式,返回 float64 类型的 NumPy 数组
@overload
def tri(
    N: int,
    M: None | int = ...,
    k: int = ...,
    dtype: None = ...,
    *,
    like: None | _SupportsArrayFunc = ...
) -> NDArray[float64]: ...

# 函数 tri 的第二个重载形式,返回 _SCT 类型的 NumPy 数组
@overload
def tri(
    N: int,
    M: None | int = ...,
    k: int = ...,
    dtype: _DTypeLike[_SCT] = ...,
    *,
    like: None | _SupportsArrayFunc = ...
) -> NDArray[_SCT]: ...

# 函数 tri 的第三个重载形式,返回任意类型的 NumPy 数组
@overload
def tri(
    N: int,
    M: None | int = ...,
    k: int = ...,
    dtype: DTypeLike = ...,
    *,
    like: None | _SupportsArrayFunc = ...
) -> NDArray[Any]: ...

# 函数 tril 的第一个重载形式,接受 _ArrayLike 类型参数 v,返回 _SCT 类型的 NumPy 数组
@overload
def tril(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...

# 函数 tril 的第二个重载形式,接受 ArrayLike 类型参数 v,返回任意类型的 NumPy 数组
@overload
def tril(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...

# 函数 triu 的第一个重载形式,接受 _ArrayLike 类型参数 v,返回 _SCT 类型的 NumPy 数组
@overload
def triu(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...

# 函数 triu 的第二个重载形式,接受 ArrayLike 类型参数 v,返回任意类型的 NumPy 数组
@overload
def triu(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...

# 函数 vander 的声明,类型检查被忽略(type: ignore[misc]),接受 _ArrayLikeInt_co 类型参数 x
# 返回类型未指定,应根据具体实现确定
def vander(
    x: _ArrayLikeInt_co,
    N: None | int = ...,
    increasing: bool = ...,



# 定义两个变量 N 和 increasing,分别类型为可空的整数或 None,和布尔值
N: None | int = ...,
increasing: bool = ...,


这段代码定义了两个变量 `N` 和 `increasing`。在类型注释中,`N` 的类型是可空的整数或者 `None`,而 `increasing` 是布尔类型。这些变量的具体值在这里用 `...` 表示,实际应用中应该有具体的赋值。
@overload
def vander(
    x: _ArrayLikeFloat_co,
    N: None | int = ...,
    increasing: bool = ...,
) -> NDArray[floating[Any]]: ...
@overload
def vander(
    x: _ArrayLikeComplex_co,
    N: None | int = ...,
    increasing: bool = ...,
) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def vander(
    x: _ArrayLikeObject_co,
    N: None | int = ...,
    increasing: bool = ...,
) -> NDArray[object_]: ...


# 生成范德蒙矩阵(Vandermonde matrix)。
# 根据不同的输入类型和参数生成不同的 V 阵(Vandermonde matrix)。
# - x: 输入数组或类数组(_ArrayLike),可以是浮点数、复数或对象类型。
# - N: V 阵的列数,如果为 None 则取 x 的长度。
# - increasing: 控制 V 阵的列的递增或递减排列。
# 返回生成的 V 阵作为浮点数、复数或对象数组。

@overload
def histogram2d(
    x: _ArrayLikeFloat_co,
    y: _ArrayLikeFloat_co,
    bins: int | Sequence[int] = ...,
    range: None | _ArrayLikeFloat_co = ...,
    density: None | bool = ...,
    weights: None | _ArrayLikeFloat_co = ...,
) -> tuple[
    NDArray[float64],
    NDArray[floating[Any]],
    NDArray[floating[Any]],
]: ...
@overload
def histogram2d(
    x: _ArrayLikeComplex_co,
    y: _ArrayLikeComplex_co,
    bins: int | Sequence[int] = ...,
    range: None | _ArrayLikeFloat_co = ...,
    density: None | bool = ...,
    weights: None | _ArrayLikeFloat_co = ...,
) -> tuple[
    NDArray[float64],
    NDArray[complexfloating[Any, Any]],
    NDArray[complexfloating[Any, Any]],
]: ...
@overload  # TODO: Sort out `bins`
def histogram2d(
    x: _ArrayLikeComplex_co,
    y: _ArrayLikeComplex_co,
    bins: Sequence[_ArrayLikeInt_co],
    range: None | _ArrayLikeFloat_co = ...,
    density: None | bool = ...,
    weights: None | _ArrayLikeFloat_co = ...,
) -> tuple[
    NDArray[float64],
    NDArray[Any],
    NDArray[Any],
]: ...


# 生成二维直方图。
# 根据输入的数组 x 和 y,以及可选的 bins、range、density 和 weights 参数生成二维直方图。
# - x: 输入数组或类数组,可以是浮点数或复数。
# - y: 输入数组或类数组,可以是浮点数或复数,与 x 的形状必须一致。
# - bins: 定义直方图箱子的数量或边界。
# - range: 定义 x 和 y 的范围。
# - density: 如果为 True,则返回的直方图是归一化的概率密度。
# - weights: 可选的权重数组,用于每个点的加权统计。
# 返回一个包含三个数组的元组,分别是直方图统计值、x 方向上的直方图箱子边界、y 方向上的直方图箱子边界。

@overload
def mask_indices(
    n: int,
    mask_func: _MaskFunc[int],
    k: int = ...,
) -> tuple[NDArray[intp], NDArray[intp]]: ...
@overload
def mask_indices(
    n: int,
    mask_func: _MaskFunc[_T],
    k: _T,
) -> tuple[NDArray[intp], NDArray[intp]]: ...


# 根据掩码函数生成索引数组的元组。
# 根据给定的参数生成用于掩码的索引数组。
# - n: 生成的索引数组的维度。
# - mask_func: 一个函数,根据索引位置返回一个布尔值数组。
# - k: 控制生成的索引与对角线的关系。
# 返回一个元组,包含两个整数数组,分别是行索引和列索引。

def tril_indices(
    n: int,
    k: int = ...,
    m: None | int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...


# 返回一个下三角矩阵的索引元组。
# 返回一个下三角矩阵的所有行列索引。
# - n: 矩阵的行数和列数。
# - k: 控制生成的索引与主对角线的关系。
# - m: 可选参数,控制生成的索引的上限。

def tril_indices_from(
    arr: NDArray[Any],
    k: int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...


# 返回给定数组的下三角矩阵的索引元组。
# 返回给定数组的下三角矩阵的所有行列索引。
# - arr: 输入的数组,返回其下三角矩阵的索引。
# - k: 控制生成的索引与主对角线的关系。

def triu_indices(
    n: int,
    k: int = ...,
    m: None | int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...


# 返回一个上三角矩阵的索引元组。
# 返回一个上三角矩阵的所有行列索引。
# - n: 矩阵的行数和列数。
# - k: 控制生成的索引与主对角线的关系。
# - m: 可选参数,控制生成的索引的上限。

def triu_indices_from(
    arr: NDArray[Any],
    k: int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...


# 返回给定数组的上三角矩阵的索引元组。
# 返回给定数组的上三角矩阵的所有行列索引。
# - arr: 输入的数组,返回其上三角矩阵的索引。
# - k: 控制生成的索引与主对角线的关系。

.\numpy\numpy\lib\_type_check_impl.py

"""Automatically adapted for numpy Sep 19, 2005 by convertcode.py

"""
import functools  # 导入 functools 模块,用于创建偏函数
__all__ = ['iscomplexobj', 'isrealobj', 'imag', 'iscomplex',
           'isreal', 'nan_to_num', 'real', 'real_if_close',
           'typename', 'mintypecode',
           'common_type']

from .._utils import set_module  # 导入 set_module 函数,用于设置模块名称
import numpy._core.numeric as _nx  # 导入 numpy 内部的 numeric 模块别名为 _nx
from numpy._core.numeric import asarray, asanyarray, isnan, zeros  # 从 numpy 内部的 numeric 模块导入特定函数
from numpy._core import overrides, getlimits  # 从 numpy 内部的 core 模块导入 overrides 和 getlimits 函数
from ._ufunclike_impl import isneginf, isposinf  # 从当前包的 _ufunclike_impl 模块导入 isneginf 和 isposinf 函数

# 创建 array_function_dispatch 的偏函数,指定 module 为 'numpy'
array_function_dispatch = functools.partial(
    overrides.array_function_dispatch, module='numpy')


# 定义 mintypecode 函数,并用 set_module 装饰器设置模块名称为 'numpy'
@set_module('numpy')
def mintypecode(typechars, typeset='GDFgdf', default='d'):
    """
    Return the character for the minimum-size type to which given types can
    be safely cast.

    The returned type character must represent the smallest size dtype such
    that an array of the returned type can handle the data from an array of
    all types in `typechars` (or if `typechars` is an array, then its
    dtype.char).

    Parameters
    ----------
    typechars : list of str or array_like
        If a list of strings, each string should represent a dtype.
        If array_like, the character representation of the array dtype is used.
    typeset : str or list of str, optional
        The set of characters that the returned character is chosen from.
        The default set is 'GDFgdf'.
    default : str, optional
        The default character, this is returned if none of the characters in
        `typechars` matches a character in `typeset`.

    Returns
    -------
    typechar : str
        The character representing the minimum-size type that was found.

    See Also
    --------
    dtype

    Examples
    --------
    >>> np.mintypecode(['d', 'f', 'S'])
    'd'
    >>> x = np.array([1.1, 2-3.j])
    >>> np.mintypecode(x)
    'D'

    >>> np.mintypecode('abceh', default='G')
    'G'

    """
    # 生成 typechars 中每个类型的字符表示,并以列表形式存储在 typecodes 中
    typecodes = ((isinstance(t, str) and t) or asarray(t).dtype.char
                 for t in typechars)
    # 计算 typecodes 和 typeset 的交集,并转换为集合 intersection
    intersection = set(t for t in typecodes if t in typeset)
    # 如果 intersection 为空集,则返回默认字符 default
    if not intersection:
        return default
    # 如果 intersection 包含 'F' 和 'd',则返回 'D'
    if 'F' in intersection and 'd' in intersection:
        return 'D'
    # 否则,返回 intersection 中字典序最小的字符
    return min(intersection, key=_typecodes_by_elsize.index)


# 定义 _real_dispatcher 函数,用于作为 real 函数的分发器
def _real_dispatcher(val):
    return (val,)


# 使用 array_function_dispatch 装饰器,将 _real_dispatcher 函数注册为 real 函数的分发实现
@array_function_dispatch(_real_dispatcher)
def real(val):
    """
    Return the real part of the complex argument.

    Parameters
    ----------
    val : array_like
        Input array.

    Returns
    -------
    out : ndarray or scalar
        The real component of the complex argument. If `val` is real, the type
        of `val` is used for the output.  If `val` has complex elements, the
        returned type is float.

    See Also
    --------
    real_if_close, imag, angle

    Examples
    --------
    >>> a = np.array([1+2j, 3+4j, 5+6j])
    >>> a.real
    array([1.,  3.,  5.])
    >>> a.real = 9
    >>> a

    """
    # 返回 val 的实部,如果 val 是复数,则返回浮点数类型的实部
    return _nx.real(val)
    # 创建一个复数数组,包含三个元素,每个元素有实部和虚部
    >>> array([9.+2.j,  9.+4.j,  9.+6.j])
    # 将复数数组 a 的实部部分替换为给定的整数数组
    >>> a.real = np.array([9, 8, 7])
    # 打印数组 a 的当前状态,实部已经被更新,虚部保持不变
    >>> a
    # 计算给定复数的实部,返回结果为包含实数部分的 numpy 数组
    >>> array([9.+2.j,  8.+4.j,  7.+6.j])
    # 计算复数 1+1j 的实部,返回结果为实数部分的浮点数
    >>> np.real(1 + 1j)
    
    """
    # 尝试获取参数 val 的实部,若无法获取则将 val 转换为 numpy 数组后再获取其实部
    try:
        return val.real
    except AttributeError:
        return asanyarray(val).real
# 定义一个辅助函数 _imag_dispatcher,接受一个参数 val,返回一个包含 val 的元组
def _imag_dispatcher(val):
    return (val,)

# 使用 array_function_dispatch 装饰器,将 _imag_dispatcher 作为分派函数
@array_function_dispatch(_imag_dispatcher)
# 定义 imag 函数,用于返回复数参数的虚部
def imag(val):
    """
    返回复数参数的虚部。

    Parameters
    ----------
    val : array_like
        输入数组。

    Returns
    -------
    out : ndarray or scalar
        复数参数的虚部。如果 val 是实数,则输出与 val 相同的类型。如果 val 包含复数元素,返回的类型是 float。

    See Also
    --------
    real, angle, real_if_close

    Examples
    --------
    >>> a = np.array([1+2j, 3+4j, 5+6j])
    >>> a.imag
    array([2.,  4.,  6.])
    >>> a.imag = np.array([8, 10, 12])
    >>> a
    array([1. +8.j,  3.+10.j,  5.+12.j])
    >>> np.imag(1 + 1j)
    1.0

    """
    try:
        return val.imag  # 尝试返回 val 的虚部属性
    except AttributeError:
        return asanyarray(val).imag  # 如果 val 没有 imag 属性,将其转换为数组后再获取虚部


# 定义一个辅助函数 _is_type_dispatcher,接受一个参数 x,返回一个包含 x 的元组
def _is_type_dispatcher(x):
    return (x,)

# 使用 array_function_dispatch 装饰器,将 _is_type_dispatcher 作为分派函数
@array_function_dispatch(_is_type_dispatcher)
# 定义 iscomplex 函数,返回一个布尔数组,指示输入元素是否为复数
def iscomplex(x):
    """
    返回一个布尔数组,其中元素为 True 表示输入元素是复数。

    检测的是输入元素是否具有非零虚部,而不是输入类型是否为复数。

    Parameters
    ----------
    x : array_like
        输入数组。

    Returns
    -------
    out : ndarray of bools
        输出布尔数组。

    See Also
    --------
    isreal
    iscomplexobj : 如果 x 是复数类型或复数数组,则返回 True。

    Examples
    --------
    >>> np.iscomplex([1+1j, 1+0j, 4.5, 3, 2, 2j])
    array([ True, False, False, False, False,  True])

    """
    ax = asanyarray(x)  # 将 x 转换为数组
    if issubclass(ax.dtype.type, _nx.complexfloating):  # 如果数组的类型是复数浮点类型
        return ax.imag != 0  # 返回虚部非零的布尔数组
    res = zeros(ax.shape, bool)  # 创建与 ax 形状相同的布尔数组
    return res[()]  # 将其转换为标量(如果需要)


# 使用 array_function_dispatch 装饰器,将 _is_type_dispatcher 作为分派函数
@array_function_dispatch(_is_type_dispatcher)
# 定义 isreal 函数,返回一个布尔数组,指示输入元素是否为实数
def isreal(x):
    """
    返回一个布尔数组,其中元素为 True 表示输入元素是实数。

    如果元素具有复数类型且虚部为零,则该元素的返回值为 True。

    Parameters
    ----------
    x : array_like
        输入数组。

    Returns
    -------
    out : ndarray, bool
        与 x 相同形状的布尔数组。

    Notes
    -----
    对于字符串或对象数组,isreal 可能会产生意外结果(见示例)。

    See Also
    --------
    iscomplex
    isrealobj : 如果 x 不是复数类型,则返回 True。

    Examples
    --------
    >>> a = np.array([1+1j, 1+0j, 4.5, 3, 2, 2j], dtype=complex)
    >>> np.isreal(a)
    array([False,  True,  True,  True,  True, False])

    函数不适用于字符串数组。

    >>> a = np.array([2j, "a"], dtype="U")
    >>> np.isreal(a)  # 警告:不适用于非逐元素比较
    False

    对于 ``dtype=object`` 的输入数组,即使其中任何元素是复数,也会返回 True。

    >>> a = np.array([1, "2", 3+4j], dtype=object)
    >>> np.isreal(a)
    array([ True,  True,  True])

    """
    isreal should not be used with object arrays
    
    # 创建一个包含复数对象的 NumPy 数组
    a = np.array([1+2j, 2+1j], dtype=object)
    # 检查数组中每个元素是否为实数,但不建议在对象数组上使用该函数
    np.isreal(a)
    # 返回一个布尔数组,表示每个元素是否为实数
    
    """
    返回 x 的虚部是否全为零的布尔值数组
    """
    return imag(x) == 0
@array_function_dispatch(_is_type_dispatcher)
# 使用 array_function_dispatch 装饰器来分派函数调用,以便根据输入类型调用合适的函数
def iscomplexobj(x):
    """
    Check for a complex type or an array of complex numbers.

    The type of the input is checked, not the value. Even if the input
    has an imaginary part equal to zero, `iscomplexobj` evaluates to True.

    Parameters
    ----------
    x : any
        The input can be of any type and shape.

    Returns
    -------
    iscomplexobj : bool
        The return value, True if `x` is of a complex type or has at least
        one complex element.

    See Also
    --------
    isrealobj, iscomplex

    Examples
    --------
    >>> np.iscomplexobj(1)
    False
    >>> np.iscomplexobj(1+0j)
    True
    >>> np.iscomplexobj([3, 1+0j, True])
    True

    """
    try:
        dtype = x.dtype
        type_ = dtype.type
    except AttributeError:
        type_ = asarray(x).dtype.type
    return issubclass(type_, _nx.complexfloating)


@array_function_dispatch(_is_type_dispatcher)
# 使用 array_function_dispatch 装饰器来分派函数调用,以便根据输入类型调用合适的函数
def isrealobj(x):
    """
    Return True if x is a not complex type or an array of complex numbers.

    The type of the input is checked, not the value. So even if the input
    has an imaginary part equal to zero, `isrealobj` evaluates to False
    if the data type is complex.

    Parameters
    ----------
    x : any
        The input can be of any type and shape.

    Returns
    -------
    y : bool
        The return value, False if `x` is of a complex type.

    See Also
    --------
    iscomplexobj, isreal

    Notes
    -----
    The function is only meant for arrays with numerical values but it
    accepts all other objects. Since it assumes array input, the return
    value of other objects may be True.

    >>> np.isrealobj('A string')
    True
    >>> np.isrealobj(False)
    True
    >>> np.isrealobj(None)
    True

    Examples
    --------
    >>> np.isrealobj(1)
    True
    >>> np.isrealobj(1+0j)
    False
    >>> np.isrealobj([3, 1+0j, True])
    False

    """
    return not iscomplexobj(x)

#-----------------------------------------------------------------------------

def _getmaxmin(t):
    # 从 numpy._core 导入 getlimits 函数
    from numpy._core import getlimits
    # 调用 getlimits.finfo 函数,传入类型 t
    f = getlimits.finfo(t)
    # 返回 f 的最大值和最小值
    return f.max, f.min


def _nan_to_num_dispatcher(x, copy=None, nan=None, posinf=None, neginf=None):
    # 返回一个元组 (x,),用于分派 nan_to_num 函数的调用
    return (x,)


@array_function_dispatch(_nan_to_num_dispatcher)
# 使用 array_function_dispatch 装饰器来分派函数调用,以便根据输入类型调用合适的函数
def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None):
    """
    Replace NaN with zero and infinity with large finite numbers (default
    behaviour) or with the numbers defined by the user using the `nan`,
    `posinf` and/or `neginf` keywords.

    If `x` is inexact, NaN is replaced by zero or by the user defined value in
    `nan` keyword, infinity is replaced by the largest finite floating point
    values representable by ``x.dtype`` or by the user defined value in
    `posinf` keyword and -infinity is replaced by the most negative finite
    floating point values representable by ``x.dtype`` or by the user defined
    value in `neginf` keyword.

    """
    # 将输入数据 `x` 转换为 NumPy 数组,保留子类信息并根据 `copy` 参数决定是否复制数据
    x = _nx.array(x, subok=True, copy=copy)
    # 获取数组 `x` 的数据类型
    xtype = x.dtype.type
    # 检查 x 是否为标量(即维度为 0)
    isscalar = (x.ndim == 0)
    
    # 如果 x 的类型不是浮点数或复数类型的子类,则根据是否是标量返回 x 的值或单个元素
    if not issubclass(xtype, _nx.inexact):
        return x[()] if isscalar else x
    
    # 检查 x 的类型是否为复数类型的子类
    iscomplex = issubclass(xtype, _nx.complexfloating)
    
    # 如果 x 是复数类型,则将 x 分成实部和虚部,否则将 x 放入一个元组中
    dest = (x.real, x.imag) if iscomplex else (x,)
    
    # 获取 x.real 的数据类型的最大值和最小值
    maxf, minf = _getmaxmin(x.real.dtype)
    
    # 如果 posinf 不为 None,则将 maxf 设为 posinf
    if posinf is not None:
        maxf = posinf
    
    # 如果 neginf 不为 None,则将 minf 设为 neginf
    if neginf is not None:
        minf = neginf
    
    # 遍历 dest 中的元素 d
    for d in dest:
        # 找到 d 中的 NaN 值的索引
        idx_nan = isnan(d)
        # 找到 d 中的正无穷值的索引
        idx_posinf = isposinf(d)
        # 找到 d 中的负无穷值的索引
        idx_neginf = isneginf(d)
        # 将 NaN 的位置替换为 nan
        _nx.copyto(d, nan, where=idx_nan)
        # 将正无穷的位置替换为 maxf
        _nx.copyto(d, maxf, where=idx_posinf)
        # 将负无穷的位置替换为 minf
        _nx.copyto(d, minf, where=idx_neginf)
    
    # 根据是否是标量返回 x 的值或单个元素
    return x[()] if isscalar else x
#-----------------------------------------------------------------------------
# 定义一个私有函数 _real_if_close_dispatcher,用于分发输入参数 a 和 tol
def _real_if_close_dispatcher(a, tol=None):
    # 返回一个包含参数 a 的元组
    return (a,)

# 使用 array_function_dispatch 装饰器,将 _real_if_close_dispatcher 注册为 real_if_close 的分发函数
@array_function_dispatch(_real_if_close_dispatcher)
def real_if_close(a, tol=100):
    """
    如果输入的数组是复数且所有虚部接近零,则返回实部。

    “接近零”的定义是 `tol` 乘以 `a` 的类型的机器 epsilon。

    Parameters
    ----------
    a : array_like
        输入数组。
    tol : float
        数组中元素的虚部的机器 epsilon 的容差。如果容差 <=1,则使用绝对容差。

    Returns
    -------
    out : ndarray
        如果 `a` 是实数,则输出与 `a` 相同的类型。如果 `a` 包含复数元素,则输出类型为 float。

    See Also
    --------
    real, imag, angle

    Notes
    -----
    机器 epsilon 因计算机和数据类型而异,但大多数平台上的 Python 浮点数的机器 epsilon 等于
    2.2204460492503131e-16。您可以使用 'np.finfo(float).eps' 打印出浮点数的机器 epsilon。

    Examples
    --------
    >>> np.finfo(float).eps
    2.2204460492503131e-16 # 可能会有所不同

    >>> np.real_if_close([2.1 + 4e-14j, 5.2 + 3e-15j], tol=1000)
    array([2.1, 5.2])
    >>> np.real_if_close([2.1 + 4e-13j, 5.2 + 3e-15j], tol=1000)
    array([2.1+4.e-13j, 5.2 + 3e-15j])

    """

    # 将输入参数转换为 ndarray 类型
    a = asanyarray(a)
    # 获取数组元素的数据类型
    type_ = a.dtype.type
    # 如果数据类型不是复数类型,则直接返回数组 a
    if not issubclass(type_, _nx.complexfloating):
        return a
    # 如果指定的容差 tol 大于 1,则使用数据类型的机器 epsilon 乘以 tol 作为新的容差值
    if tol > 1:
        f = getlimits.finfo(type_)
        tol = f.eps * tol
    # 如果数组 a 的所有元素的虚部的绝对值均小于 tol,则将数组 a 转换为实部数组
    if _nx.all(_nx.absolute(a.imag) < tol):
        a = a.real
    # 返回处理后的数组 a
    return a


#-----------------------------------------------------------------------------
# 将数据类型代码映射到其描述的字典
_namefromtype = {'S1': 'character',
                 '?': 'bool',
                 'b': 'signed char',
                 'B': 'unsigned char',
                 'h': 'short',
                 'H': 'unsigned short',
                 'i': 'integer',
                 'I': 'unsigned integer',
                 'l': 'long integer',
                 'L': 'unsigned long integer',
                 'q': 'long long integer',
                 'Q': 'unsigned long long integer',
                 'f': 'single precision',
                 'd': 'double precision',
                 'g': 'long precision',
                 'F': 'complex single precision',
                 'D': 'complex double precision',
                 'G': 'complex long double precision',
                 'S': 'string',
                 'U': 'unicode',
                 'V': 'void',
                 'O': 'object'
                 }

# 使用 set_module 装饰器将函数 typename 设置为属于 'numpy' 模块的函数
@set_module('numpy')
def typename(char):
    """
    根据给定的数据类型代码返回描述信息。

    Parameters
    ----------
    char : str
        数据类型代码。

    Returns
    -------
    out : str
        给定数据类型代码的描述信息。

    See Also
    --------
    dtype

    """
    Examples
    --------
    # 定义一个类型字符列表,包含多种数据类型的表示符号
    >>> typechars = ['S1', '?', 'B', 'D', 'G', 'F', 'I', 'H', 'L', 'O', 'Q',
    ...              'S', 'U', 'V', 'b', 'd', 'g', 'f', 'i', 'h', 'l', 'q']
    # 遍历每个类型字符,并输出其对应的类型名称
    >>> for typechar in typechars:
    ...     print(typechar, ' : ', np.typename(typechar))
    ...
    S1  :  character
    ?  :  bool
    B  :  unsigned char
    D  :  complex double precision
    G  :  complex long double precision
    F  :  complex single precision
    I  :  unsigned integer
    H  :  unsigned short
    L  :  unsigned long integer
    O  :  object
    Q  :  unsigned long long integer
    S  :  string
    U  :  unicode
    V  :  void
    b  :  signed char
    d  :  double precision
    g  :  long precision
    f  :  single precision
    i  :  integer
    h  :  short
    l  :  long integer
    q  :  long long integer
    """
    # 根据字符 char 查询并返回对应的类型名称 _namefromtype[char]
    return _namefromtype[char]
# Define two lists that represent possible data types for arrays: floating point types and complex types respectively.
array_type = [[_nx.float16, _nx.float32, _nx.float64, _nx.longdouble],
              [None, _nx.complex64, _nx.complex128, _nx.clongdouble]]

# Define a dictionary that maps each data type to its precision level.
array_precision = {_nx.float16: 0,
                   _nx.float32: 1,
                   _nx.float64: 2,
                   _nx.longdouble: 3,
                   _nx.complex64: 1,
                   _nx.complex128: 2,
                   _nx.clongdouble: 3}


# Dispatcher function that returns all input arrays.
def _common_type_dispatcher(*arrays):
    return arrays


# Decorated function that computes the common scalar type among input arrays.
@array_function_dispatch(_common_type_dispatcher)
def common_type(*arrays):
    """
    Return a scalar type which is common to the input arrays.

    The return type will always be an inexact (i.e. floating point) scalar
    type, even if all the arrays are integer arrays. If one of the inputs is
    an integer array, the minimum precision type that is returned is a
    64-bit floating point dtype.

    All input arrays except int64 and uint64 can be safely cast to the
    returned dtype without loss of information.

    Parameters
    ----------
    array1, array2, ... : ndarrays
        Input arrays.

    Returns
    -------
    out : data type code
        Data type code.

    See Also
    --------
    dtype, mintypecode

    Examples
    --------
    >>> np.common_type(np.arange(2, dtype=np.float32))
    <class 'numpy.float32'>
    >>> np.common_type(np.arange(2, dtype=np.float32), np.arange(2))
    <class 'numpy.float64'>
    >>> np.common_type(np.arange(4), np.array([45, 6.j]), np.array([45.0]))
    <class 'numpy.complex128'>

    """
    # Initialize variables to track if complex types are present and the maximum precision found.
    is_complex = False
    precision = 0
    
    # Iterate through each array to determine its type and update precision accordingly.
    for a in arrays:
        t = a.dtype.type  # Get the type of the array's elements.
        if iscomplexobj(a):  # Check if the array contains complex numbers.
            is_complex = True
        if issubclass(t, _nx.integer):  # Check if the type is a subclass of integer.
            p = 2  # Set precision to that of a double for integer types.
        else:
            p = array_precision.get(t, None)  # Retrieve precision level from array_precision dictionary.
            if p is None:
                raise TypeError("can't get common type for non-numeric array")  # Raise error for non-numeric arrays.
        precision = max(precision, p)  # Update maximum precision encountered.
    
    # Determine and return the common type based on whether complex types were encountered.
    if is_complex:
        return array_type[1][precision]  # Return the complex type with the maximum precision.
    else:
        return array_type[0][precision]  # Return the floating point type with the maximum precision.

.\numpy\numpy\lib\_type_check_impl.pyi

# 从 collections.abc 导入 Container 和 Iterable 接口
from collections.abc import Container, Iterable
# 从 typing 模块导入 Literal 别名 L,Any 类型,overload 装饰器,TypeVar 类型变量和 Protocol 协议
from typing import (
    Literal as L,
    Any,
    overload,
    TypeVar,
    Protocol,
)

# 导入 numpy 库,并将其别名为 np
import numpy as np
# 从 numpy 中导入 dtype、generic、floating、float64、complexfloating 和 integer
from numpy import (
    dtype,
    generic,
    floating,
    float64,
    complexfloating,
    integer,
)

# 从 numpy._typing 模块导入各种类型变量
from numpy._typing import (
    ArrayLike,
    DTypeLike,
    NBitBase,
    NDArray,
    _64Bit,
    _SupportsDType,
    _ScalarLike_co,
    _ArrayLike,
    _DTypeLikeComplex,
)

# 定义类型变量 _T 和 _T_co
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
# 定义类型变量 _SCT,限定为 generic 的子类
_SCT = TypeVar("_SCT", bound=generic)
# 定义类型变量 _NBit1 和 _NBit2,限定为 NBitBase 的子类

# 定义 _SupportsReal 协议,泛型为 _T_co
class _SupportsReal(Protocol[_T_co]):
    @property
    def real(self) -> _T_co: ...

# 定义 _SupportsImag 协议,泛型为 _T_co
class _SupportsImag(Protocol[_T_co]):
    @property
    def imag(self) -> _T_co: ...

# 定义 __all__ 列表,用于模块导出

# 定义函数 mintypecode,参数为 typechars、typeset 和 default,返回值为 str 类型
def mintypecode(
    typechars: Iterable[str | ArrayLike],
    typeset: Container[str] = ...,
    default: str = ...,
) -> str: ...

# 函数 real 的重载定义,参数为 _SupportsReal 或 ArrayLike 类型,返回值为 _T 或 NDArray[Any]
@overload
def real(val: _SupportsReal[_T]) -> _T: ...
@overload
def real(val: ArrayLike) -> NDArray[Any]: ...

# 函数 imag 的重载定义,参数为 _SupportsImag 或 ArrayLike 类型,返回值为 _T 或 NDArray[Any]
@overload
def imag(val: _SupportsImag[_T]) -> _T: ...
@overload
def imag(val: ArrayLike) -> NDArray[Any]: ...

# 函数 iscomplex 的重载定义,参数为 _ScalarLike_co 或 ArrayLike 类型,返回值为 np.bool 类型
@overload
def iscomplex(x: _ScalarLike_co) -> np.bool: ...  # type: ignore[misc]
@overload
def iscomplex(x: ArrayLike) -> NDArray[np.bool]: ...

# 函数 isreal 的重载定义,参数为 _ScalarLike_co 或 ArrayLike 类型,返回值为 np.bool 类型
@overload
def isreal(x: _ScalarLike_co) -> np.bool: ...  # type: ignore[misc]
@overload
def isreal(x: ArrayLike) -> NDArray[np.bool]: ...

# 函数 iscomplexobj,参数为 _SupportsDType[dtype[Any]] 或 ArrayLike 类型,返回值为 bool 类型
def iscomplexobj(x: _SupportsDType[dtype[Any]] | ArrayLike) -> bool: ...

# 函数 isrealobj,参数为 _SupportsDType[dtype[Any]] 或 ArrayLike 类型,返回值为 bool 类型
def isrealobj(x: _SupportsDType[dtype[Any]] | ArrayLike) -> bool: ...

# 函数 nan_to_num 的重载定义,参数为不同类型的 x,返回值类型根据参数类型不同而定
@overload
def nan_to_num(  # type: ignore[misc]
    x: _SCT,
    copy: bool = ...,
    nan: float = ...,
    posinf: None | float = ...,
    neginf: None | float = ...,
) -> _SCT: ...
@overload
def nan_to_num(
    x: _ScalarLike_co,
    copy: bool = ...,
    nan: float = ...,
    posinf: None | float = ...,
    neginf: None | float = ...,
) -> Any: ...
@overload
def nan_to_num(
    x: _ArrayLike[_SCT],
    copy: bool = ...,
    nan: float = ...,
    posinf: None | float = ...,
    neginf: None | float = ...,
) -> NDArray[_SCT]: ...
@overload
def nan_to_num(
    x: ArrayLike,
    copy: bool = ...,
    nan: float = ...,
    posinf: None | float = ...,
    neginf: None | float = ...,
) -> NDArray[Any]: ...

# 函数 real_if_close 的重载定义,参数为不同类型的 a 和 tol,返回值类型根据参数类型不同而定
@overload
def real_if_close(  # type: ignore[misc]
    a: _ArrayLike[complexfloating[_NBit1, _NBit1]],
    tol: float = ...,
) -> NDArray[floating[_NBit1]] | NDArray[complexfloating[_NBit1, _NBit1]]: ...
@overload
def real_if_close(
    a: _ArrayLike[_SCT],
    tol: float = ...,
) -> NDArray[_SCT]: ...
@overload
def real_if_close(
    a: ArrayLike,
    tol: float = ...,
) -> NDArray[Any]: ...

# 函数 typename 的重载定义,参数为字符类型的 char,返回值类型根据参数类型不同而定
@overload
def typename(char: L['S1']) -> L['character']: ...
@overload
def typename(char: L['?']) -> L['bool']: ...
@overload
def typename(char: L['b']) -> L['signed char']: ...
# 函数重载定义,接受字符类型 'b',返回类型为 'signed char'

@overload
def typename(char: L['B']) -> L['unsigned char']: ...
# 函数重载定义,接受字符类型 'B',返回类型为 'unsigned char'

@overload
def typename(char: L['h']) -> L['short']: ...
# 函数重载定义,接受字符类型 'h',返回类型为 'short'

@overload
def typename(char: L['H']) -> L['unsigned short']: ...
# 函数重载定义,接受字符类型 'H',返回类型为 'unsigned short'

@overload
def typename(char: L['i']) -> L['integer']: ...
# 函数重载定义,接受字符类型 'i',返回类型为 'integer'

@overload
def typename(char: L['I']) -> L['unsigned integer']: ...
# 函数重载定义,接受字符类型 'I',返回类型为 'unsigned integer'

@overload
def typename(char: L['l']) -> L['long integer']: ...
# 函数重载定义,接受字符类型 'l',返回类型为 'long integer'

@overload
def typename(char: L['L']) -> L['unsigned long integer']: ...
# 函数重载定义,接受字符类型 'L',返回类型为 'unsigned long integer'

@overload
def typename(char: L['q']) -> L['long long integer']: ...
# 函数重载定义,接受字符类型 'q',返回类型为 'long long integer'

@overload
def typename(char: L['Q']) -> L['unsigned long long integer']: ...
# 函数重载定义,接受字符类型 'Q',返回类型为 'unsigned long long integer'

@overload
def typename(char: L['f']) -> L['single precision']: ...
# 函数重载定义,接受字符类型 'f',返回类型为 'single precision'

@overload
def typename(char: L['d']) -> L['double precision']: ...
# 函数重载定义,接受字符类型 'd',返回类型为 'double precision'

@overload
def typename(char: L['g']) -> L['long precision']: ...
# 函数重载定义,接受字符类型 'g',返回类型为 'long precision'

@overload
def typename(char: L['F']) -> L['complex single precision']: ...
# 函数重载定义,接受字符类型 'F',返回类型为 'complex single precision'

@overload
def typename(char: L['D']) -> L['complex double precision']: ...
# 函数重载定义,接受字符类型 'D',返回类型为 'complex double precision'

@overload
def typename(char: L['G']) -> L['complex long double precision']: ...
# 函数重载定义,接受字符类型 'G',返回类型为 'complex long double precision'

@overload
def typename(char: L['S']) -> L['string']: ...
# 函数重载定义,接受字符类型 'S',返回类型为 'string'

@overload
def typename(char: L['U']) -> L['unicode']: ...
# 函数重载定义,接受字符类型 'U',返回类型为 'unicode'

@overload
def typename(char: L['V']) -> L['void']: ...
# 函数重载定义,接受字符类型 'V',返回类型为 'void'

@overload
def typename(char: L['O']) -> L['object']: ...
# 函数重载定义,接受字符类型 'O',返回类型为 'object'

@overload
def common_type(  # type: ignore[misc]
    *arrays: _SupportsDType[dtype[
        integer[Any]
    ]]
) -> type[floating[_64Bit]]: ...
# 函数重载定义,接受任意数量的整数类型数组,返回类型为 64 位浮点数的类型

@overload
def common_type(  # type: ignore[misc]
    *arrays: _SupportsDType[dtype[
        floating[_NBit1]
    ]]
) -> type[floating[_NBit1]]: ...
# 函数重载定义,接受任意数量的指定位数浮点数类型数组,返回类型为指定位数浮点数的类型

@overload
def common_type(  # type: ignore[misc]
    *arrays: _SupportsDType[dtype[
        integer[Any] | floating[_NBit1]
    ]]
) -> type[floating[_NBit1 | _64Bit]]: ...
# 函数重载定义,接受任意数量的整数或指定位数浮点数类型数组,返回类型为指定位数浮点数或64位浮点数的类型

@overload
def common_type(  # type: ignore[misc]
    *arrays: _SupportsDType[dtype[
        floating[_NBit1] | complexfloating[_NBit2, _NBit2]
    ]]
) -> type[complexfloating[_NBit1 | _NBit2, _NBit1 | _NBit2]]: ...
# 函数重载定义,接受任意数量的指定位数浮点数或复数类型数组,返回类型为复数类型的类型

@overload
def common_type(
    *arrays: _SupportsDType[dtype[
        integer[Any] | floating[_NBit1] | complexfloating[_NBit2, _NBit2]
    ]]
) -> type[complexfloating[_64Bit | _NBit1 | _NBit2, _64Bit | _NBit1 | _NBit2]]: ...
# 函数重载定义,接受任意数量的整数、指定位数浮点数或复数类型数组,返回类型为复数类型、指定位数浮点数或64位浮点数的类型

.\numpy\numpy\lib\_ufunclike_impl.py

"""
Module of functions that are like ufuncs in acting on arrays and optionally
storing results in an output array.

"""
__all__ = ['fix', 'isneginf', 'isposinf']  # 将这些函数添加到模块的公开接口中

import numpy._core.numeric as nx  # 导入 NumPy 核心模块的 numeric 子模块,用别名 nx
from numpy._core.overrides import array_function_dispatch  # 导入数组函数分发装饰器
import warnings  # 导入警告模块
import functools  # 导入 functools 模块


def _dispatcher(x, out=None):
    """
    A simple dispatcher function returning input and output arrays.

    Parameters
    ----------
    x : array_like
        The input array to be processed.
    out : ndarray, optional
        A pre-allocated output array where results are stored if provided.

    Returns
    -------
    tuple
        A tuple containing input and output arrays.
    """
    return (x, out)


@array_function_dispatch(_dispatcher, verify=False, module='numpy')
def fix(x, out=None):
    """
    Round to nearest integer towards zero.

    Round an array of floats element-wise to nearest integer towards zero.
    The rounded values are returned as floats.

    Parameters
    ----------
    x : array_like
        An array of floats to be rounded.
    out : ndarray, optional
        A location into which the result is stored. If provided, it must have
        a shape that the input broadcasts to. If not provided or None, a
        freshly-allocated array is returned.

    Returns
    -------
    out : ndarray of floats
        A float array with the same dimensions as the input.
        If second argument is not supplied then a float array is returned
        with the rounded values.

        If a second argument is supplied the result is stored there.
        The return value `out` is then a reference to that array.

    See Also
    --------
    rint, trunc, floor, ceil
    around : Round to given number of decimals

    Examples
    --------
    >>> np.fix(3.14)
    3.0
    >>> np.fix(3)
    3.0
    >>> np.fix([2.1, 2.9, -2.1, -2.9])
    array([ 2.,  2., -2., -2.])

    """
    # promote back to an array if flattened
    res = nx.asanyarray(nx.ceil(x, out=out))  # 对输入数组向上取整并转换为任意数组类型
    res = nx.floor(x, out=res, where=nx.greater_equal(x, 0))  # 对非负数部分向下取整

    # when no out argument is passed and no subclasses are involved, flatten
    # scalars
    if out is None and type(res) is nx.ndarray:
        res = res[()]  # 如果没有传入 out 参数且结果不是子类,则将结果扁平化为标量
    return res


@array_function_dispatch(_dispatcher, verify=False, module='numpy')
def isposinf(x, out=None):
    """
    Test element-wise for positive infinity, return result as bool array.

    Parameters
    ----------
    x : array_like
        The input array.
    out : array_like, optional
        A location into which the result is stored. If provided, it must have a
        shape that the input broadcasts to. If not provided or None, a
        freshly-allocated boolean array is returned.

    Returns
    -------
    out : ndarray of bools
        Boolean array indicating where the input is positive infinity.

    """
    # Function not fully implemented, placeholder for actual implementation
    pass
    # 使用 nx.isinf(x) 函数检查输入数组 x 中的元素是否为正无穷
    is_inf = nx.isinf(x)
    
    # 尝试计算 ~nx.signbit(x),即 x 中元素的符号位是否为非负
    try:
        signbit = ~nx.signbit(x)
    # 如果出现 TypeError,说明输入 x 包含不支持的数据类型
    except TypeError as e:
        # 获取 x 转换为任意数组后的数据类型
        dtype = nx.asanyarray(x).dtype
        # 抛出详细的 TypeError,指出不支持该数据类型进行此操作
        raise TypeError(f'This operation is not supported for {dtype} values '
                        'because it would be ambiguous.') from e
    # 如果没有异常,则计算逻辑与结果并存储到参数 out 中
    else:
        # 返回逻辑与的结果,即正无穷且符号位为非负的元素
        return nx.logical_and(is_inf, signbit, out)
# 使用装饰器为函数添加分派机制,用于在numpy模块中的函数调用
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
# 定义了一个函数isneginf,用于检测输入数组中的元素是否为负无穷,并返回布尔数组
def isneginf(x, out=None):
    """
    Test element-wise for negative infinity, return result as bool array.

    Parameters
    ----------
    x : array_like
        The input array.
    out : array_like, optional
        A location into which the result is stored. If provided, it must have a
        shape that the input broadcasts to. If not provided or None, a
        freshly-allocated boolean array is returned.

    Returns
    -------
    out : ndarray
        A boolean array with the same dimensions as the input.
        If second argument is not supplied then a numpy boolean array is
        returned with values True where the corresponding element of the
        input is negative infinity and values False where the element of
        the input is not negative infinity.

        If a second argument is supplied the result is stored there. If the
        type of that array is a numeric type the result is represented as
        zeros and ones, if the type is boolean then as False and True. The
        return value `out` is then a reference to that array.

    See Also
    --------
    isinf, isposinf, isnan, isfinite

    Notes
    -----
    NumPy uses the IEEE Standard for Binary Floating-Point for Arithmetic
    (IEEE 754).

    Errors result if the second argument is also supplied when x is a scalar
    input, if first and second arguments have different shapes, or if the
    first argument has complex values.

    Examples
    --------
    >>> np.isneginf(-np.inf)
    True
    >>> np.isneginf(np.inf)
    False
    >>> np.isneginf([-np.inf, 0., np.inf])
    array([ True, False, False])

    >>> x = np.array([-np.inf, 0., np.inf])
    >>> y = np.array([2, 2, 2])
    >>> np.isneginf(x, y)
    array([1, 0, 0])
    >>> y
    array([1, 0, 0])

    """
    # 检测输入数组中的元素是否为正无穷,返回布尔数组
    is_inf = nx.isinf(x)
    try:
        # 检测输入数组中的元素符号位,如果无法比较则引发TypeError异常
        signbit = nx.signbit(x)
    except TypeError as e:
        # 获取输入数组的数据类型,并抛出错误以避免歧义的操作
        dtype = nx.asanyarray(x).dtype
        raise TypeError(f'This operation is not supported for {dtype} values '
                        'because it would be ambiguous.') from e
    else:
        # 返回元素级别的逻辑与运算结果,即元素同时为负无穷和带符号位时为True,否则为False
        return nx.logical_and(is_inf, signbit, out)

.\numpy\numpy\lib\_ufunclike_impl.pyi

# 引入必要的类型和模块
from typing import Any, overload, TypeVar

import numpy as np
from numpy import floating, object_
from numpy._typing import (
    NDArray,
    _FloatLike_co,
    _ArrayLikeFloat_co,
    _ArrayLikeObject_co,
)

# 定义一个类型变量 _ArrayType,它是一个绑定了 NDArray[Any] 的类型变量
_ArrayType = TypeVar("_ArrayType", bound=NDArray[Any])

# __all__ 列表用于声明在 from module import * 时需要导出的符号
__all__: list[str]

# 以下是函数 fix 的多个重载定义,用于修正不同类型输入的数据类型
@overload
def fix(
    x: _FloatLike_co,
    out: None = ...,
) -> floating[Any]: ...

@overload
def fix(
    x: _ArrayLikeFloat_co,
    out: None = ...,
) -> NDArray[floating[Any]]: ...

@overload
def fix(
    x: _ArrayLikeObject_co,
    out: None = ...,
) -> NDArray[object_]: ...

@overload
def fix(
    x: _ArrayLikeFloat_co | _ArrayLikeObject_co,
    out: _ArrayType,
) -> _ArrayType: ...

# 以下是函数 isposinf 的多个重载定义,用于检查输入是否为正无穷
@overload
def isposinf(
    x: _FloatLike_co,
    out: None = ...,
) -> np.bool: ...

@overload
def isposinf(
    x: _ArrayLikeFloat_co,
    out: None = ...,
) -> NDArray[np.bool]: ...

@overload
def isposinf(
    x: _ArrayLikeFloat_co,
    out: _ArrayType,
) -> _ArrayType: ...

# 以下是函数 isneginf 的多个重载定义,用于检查输入是否为负无穷
@overload
def isneginf(
    x: _FloatLike_co,
    out: None = ...,
) -> np.bool: ...

@overload
def isneginf(
    x: _ArrayLikeFloat_co,
    out: None = ...,
) -> NDArray[np.bool]: ...

@overload
def isneginf(
    x: _ArrayLikeFloat_co,
    out: _ArrayType,
) -> _ArrayType: ...

.\numpy\numpy\lib\_user_array_impl.py

"""
Container class for backward compatibility with NumArray.

The user_array.container class exists for backward compatibility with NumArray
and is not meant to be used in new code. If you need to create an array
container class, we recommend either creating a class that wraps an ndarray
or subclasses ndarray.

"""
from numpy._core import (
    array, asarray, absolute, add, subtract, multiply, divide,
    remainder, power, left_shift, right_shift, bitwise_and, bitwise_or,
    bitwise_xor, invert, less, less_equal, not_equal, equal, greater,
    greater_equal, shape, reshape, arange, sin, sqrt, transpose
)


class container:
    """
    container(data, dtype=None, copy=True)

    Standard container-class for easy multiple-inheritance.

    Methods
    -------
    copy
        Returns a copy of the container.
    tostring
        Converts the array to a string representation.
    byteswap
        Swaps the byte order of the array.
    astype
        Converts the array to the specified data type.

    """
    def __init__(self, data, dtype=None, copy=True):
        # Initialize the container with a NumPy array created from the provided data.
        self.array = array(data, dtype, copy=copy)

    def __repr__(self):
        # Returns a string representation of the container class and its array contents.
        if self.ndim > 0:
            return self.__class__.__name__ + repr(self.array)[len("array"):]
        else:
            return self.__class__.__name__ + "(" + repr(self.array) + ")"

    def __array__(self, t=None):
        # Converts the container's array to the specified data type if provided, otherwise returns as is.
        if t:
            return self.array.astype(t)
        return self.array

    # Array as sequence
    def __len__(self):
        # Returns the length of the container's array.
        return len(self.array)

    def __getitem__(self, index):
        # Retrieves an item or slice from the container's array.
        return self._rc(self.array[index])

    def __setitem__(self, index, value):
        # Sets an item or slice in the container's array.
        self.array[index] = asarray(value, self.dtype)

    def __abs__(self):
        # Returns the absolute values of the container's array elements.
        return self._rc(absolute(self.array))

    def __neg__(self):
        # Returns the negation of the container's array elements.
        return self._rc(-self.array)

    def __add__(self, other):
        # Adds another array or scalar to the container's array.
        return self._rc(self.array + asarray(other))

    __radd__ = __add__

    def __iadd__(self, other):
        # Performs in-place addition with another array or scalar.
        add(self.array, other, self.array)
        return self

    def __sub__(self, other):
        # Subtracts another array or scalar from the container's array.
        return self._rc(self.array - asarray(other))

    def __rsub__(self, other):
        # Subtracts the container's array from another array or scalar.
        return self._rc(asarray(other) - self.array)

    def __isub__(self, other):
        # Performs in-place subtraction with another array or scalar.
        subtract(self.array, other, self.array)
        return self

    def __mul__(self, other):
        # Multiplies the container's array by another array or scalar.
        return self._rc(multiply(self.array, asarray(other)))

    __rmul__ = __mul__

    def __imul__(self, other):
        # Performs in-place multiplication with another array or scalar.
        multiply(self.array, other, self.array)
        return self

    def __div__(self, other):
        # Divides the container's array by another array or scalar.
        return self._rc(divide(self.array, asarray(other)))

    def __rdiv__(self, other):
        # Divides another array or scalar by the container's array.
        return self._rc(divide(asarray(other), self.array))

    def __idiv__(self, other):
        # Performs in-place division with another array or scalar.
        divide(self.array, other, self.array)
        return self

    def __mod__(self, other):
        # Computes the remainder of the container's array divided by another array or scalar.
        return self._rc(remainder(self.array, other))

    def __rmod__(self, other):
        # Computes the remainder of another array or scalar divided by the container's array.
        return self._rc(remainder(other, self.array))

    def __imod__(self, other):
        # Performs in-place computation of remainder with another array or scalar.
        remainder(self.array, other, self.array)
        return self
    # 定义实例方法 __divmod__,实现对象自身数组与另一个对象的除法和取余操作
    def __divmod__(self, other):
        return (self._rc(divide(self.array, other)),
                self._rc(remainder(self.array, other)))

    # 定义反向实例方法 __rdivmod__,实现另一个对象与对象自身数组的除法和取余操作
    def __rdivmod__(self, other):
        return (self._rc(divide(other, self.array)),
                self._rc(remainder(other, self.array)))

    # 定义实例方法 __pow__,实现对象自身数组的幂运算
    def __pow__(self, other):
        return self._rc(power(self.array, asarray(other)))

    # 定义反向实例方法 __rpow__,实现另一个对象与对象自身数组的幂运算
    def __rpow__(self, other):
        return self._rc(power(asarray(other), self.array))

    # 定义增强赋值方法 __ipow__,实现对象自身数组的就地幂运算
    def __ipow__(self, other):
        power(self.array, other, self.array)
        return self

    # 定义实例方法 __lshift__,实现对象自身数组的左移位操作
    def __lshift__(self, other):
        return self._rc(left_shift(self.array, other))

    # 定义实例方法 __rshift__,实现对象自身数组的右移位操作
    def __rshift__(self, other):
        return self._rc(right_shift(self.array, other))

    # 定义反向实例方法 __rlshift__,实现另一个对象与对象自身数组的左移位操作
    def __rlshift__(self, other):
        return self._rc(left_shift(other, self.array))

    # 定义反向实例方法 __rrshift__,实现另一个对象与对象自身数组的右移位操作
    def __rrshift__(self, other):
        return self._rc(right_shift(other, self.array))

    # 定义增强赋值方法 __ilshift__,实现对象自身数组的就地左移位操作
    def __ilshift__(self, other):
        left_shift(self.array, other, self.array)
        return self

    # 定义增强赋值方法 __irshift__,实现对象自身数组的就地右移位操作
    def __irshift__(self, other):
        right_shift(self.array, other, self.array)
        return self

    # 定义实例方法 __and__,实现对象自身数组与另一个对象的按位与操作
    def __and__(self, other):
        return self._rc(bitwise_and(self.array, other))

    # 定义反向实例方法 __rand__,实现另一个对象与对象自身数组的按位与操作
    def __rand__(self, other):
        return self._rc(bitwise_and(other, self.array))

    # 定义增强赋值方法 __iand__,实现对象自身数组的就地按位与操作
    def __iand__(self, other):
        bitwise_and(self.array, other, self.array)
        return self

    # 定义实例方法 __xor__,实现对象自身数组与另一个对象的按位异或操作
    def __xor__(self, other):
        return self._rc(bitwise_xor(self.array, other))

    # 定义反向实例方法 __rxor__,实现另一个对象与对象自身数组的按位异或操作
    def __rxor__(self, other):
        return self._rc(bitwise_xor(other, self.array))

    # 定义增强赋值方法 __ixor__,实现对象自身数组的就地按位异或操作
    def __ixor__(self, other):
        bitwise_xor(self.array, other, self.array)
        return self

    # 定义实例方法 __or__,实现对象自身数组与另一个对象的按位或操作
    def __or__(self, other):
        return self._rc(bitwise_or(self.array, other))

    # 定义反向实例方法 __ror__,实现另一个对象与对象自身数组的按位或操作
    def __ror__(self, other):
        return self._rc(bitwise_or(other, self.array))

    # 定义增强赋值方法 __ior__,实现对象自身数组的就地按位或操作
    def __ior__(self, other):
        bitwise_or(self.array, other, self.array)
        return self

    # 定义实例方法 __pos__,实现对象自身数组的正运算
    def __pos__(self):
        return self._rc(self.array)

    # 定义实例方法 __invert__,实现对象自身数组的按位取反操作
    def __invert__(self):
        return self._rc(invert(self.array))

    # 定义私有方法 _scalarfunc,根据对象数组的维度返回相应的标量函数结果
    def _scalarfunc(self, func):
        if self.ndim == 0:
            return func(self[0])
        else:
            raise TypeError(
                "only rank-0 arrays can be converted to Python scalars.")

    # 定义实例方法 __complex__,实现对象自身数组的复数类型转换
    def __complex__(self):
        return self._scalarfunc(complex)

    # 定义实例方法 __float__,实现对象自身数组的浮点数类型转换
    def __float__(self):
        return self._scalarfunc(float)

    # 定义实例方法 __int__,实现对象自身数组的整数类型转换
    def __int__(self):
        return self._scalarfunc(int)

    # 定义实例方法 __hex__,实现对象自身数组的十六进制类型转换
    def __hex__(self):
        return self._scalarfunc(hex)

    # 定义实例方法 __oct__,实现对象自身数组的八进制类型转换
    def __oct__(self):
        return self._scalarfunc(oct)

    # 定义实例方法 __lt__,实现对象自身数组与另一个对象的小于比较操作
    def __lt__(self, other):
        return self._rc(less(self.array, other))

    # 定义实例方法 __le__,实现对象自身数组与另一个对象的小于等于比较操作
    def __le__(self, other):
        return self._rc(less_equal(self.array, other))

    # 定义实例方法 __eq__,实现对象自身数组与另一个对象的等于比较操作
    def __eq__(self, other):
        return self._rc(equal(self.array, other))

    # 定义实例方法 __ne__,实现对象自身数组与另一个对象的不等于比较操作
    def __ne__(self, other):
        return self._rc(not_equal(self.array, other))
    # 定义大于比较方法,返回数组中每个元素与给定值的比较结果
    def __gt__(self, other):
        return self._rc(greater(self.array, other))

    # 定义大于等于比较方法,返回数组中每个元素与给定值的比较结果
    def __ge__(self, other):
        return self._rc(greater_equal(self.array, other))

    # 复制数组
    def copy(self):
        ""
        return self._rc(self.array.copy())

    # 返回数组的二进制字符串表示
    def tostring(self):
        ""
        return self.array.tostring()

    # 返回数组的字节表示
    def tobytes(self):
        ""
        return self.array.tobytes()

    # 交换数组中的字节顺序
    def byteswap(self):
        ""
        return self._rc(self.array.byteswap())

    # 返回数组的副本,类型转换为指定类型
    def astype(self, typecode):
        ""
        return self._rc(self.array.astype(typecode))

    # 返回数组或数组副本
    def _rc(self, a):
        if len(shape(a)) == 0:
            return a
        else:
            return self.__class__(a)

    # 返回新创建的数组对象
    def __array_wrap__(self, *args):
        return self.__class__(args[0])

    # 设置对象属性值
    def __setattr__(self, attr, value):
        if attr == 'array':
            object.__setattr__(self, attr, value)
            return
        try:
            self.array.__setattr__(attr, value)
        except AttributeError:
            object.__setattr__(self, attr, value)

    # 在其它尝试失败后调用的方法,获取对象属性值
    def __getattr__(self, attr):
        if (attr == 'array'):
            return object.__getattribute__(self, attr)
        return self.array.__getattribute__(attr)
#############################################################
# Test of class container
#############################################################

# 检查是否处于主模块下执行,以便进行测试
if __name__ == '__main__':
    # 创建一个包含 10000 个元素的一维数组,然后将其重塑为 100x100 的二维数组
    temp = reshape(arange(10000), (100, 100))

    # 使用 container 类来包装二维数组 temp
    ua = container(temp)
    # 输出 ua 对象的属性列表
    print(dir(ua))
    # 打印数组的形状信息
    print(shape(ua), ua.shape)  # I have changed Numeric.py

    # 提取 ua 的一个子数组 ua_small,包含前三行和前五列的部分
    ua_small = ua[:3, :5]
    # 打印 ua_small 的内容
    print(ua_small)
    # 修改 ua_small 的第一个元素为 10,验证其对原数组 ua 的影响
    # 此处注释表明修改 ua_small 不应该影响 ua[0,0]
    ua_small[0, 0] = 10
    # 打印修改后的 ua_small 的第一个元素以及原始数组 ua 的第一个元素
    print(ua_small[0, 0], ua[0, 0])
    # 对 ua_small 应用数学函数操作
    print(sin(ua_small) / 3. * 6. + sqrt(ua_small ** 2))
    # 比较 ua_small 中的元素是否小于 103,并输出结果和类型
    print(less(ua_small, 103), type(less(ua_small, 103)))
    # 计算 ua_small 与一个形状相匹配的数组的乘积,并输出结果的类型
    print(type(ua_small * reshape(arange(15), shape(ua_small))))
    # 将 ua_small 重塑为 5x3 的数组,并打印结果
    print(reshape(ua_small, (5, 3)))
    # 对 ua_small 进行转置操作,并输出结果
    print(transpose(ua_small))