NumPy-源码解析-七十九-

35 阅读1小时+

NumPy 源码解析(七十九)

.\numpy\numpy\_core\src\umath\_scaled_float_dtype.c

/*
 * This file implements a basic scaled float64 DType.  The reason is to have
 * a simple parametric DType for testing.  It is not meant to be a useful
 * DType by itself, but due to the scaling factor has similar properties as
 * a Unit DType.
 *
 * The code here should be seen as a work in progress.  Some choices are made
 * to test certain code paths, but that does not mean that they must not
 * be modified.
 *
 * NOTE: The tests were initially written using private API and ABI, ideally
 *       they should be replaced/modified with versions using public API.
 */

#define NPY_NO_DEPRECATED_API NPY_API_VERSION    /* Ensure no deprecated API is used */
#define _MULTIARRAYMODULE                        /* Define _MULTIARRAYMODULE */
#define _UMATHMODULE                             /* Define _UMATHMODULE */

#include "numpy/ndarrayobject.h"                 /* Include necessary headers */
#include "numpy/ufuncobject.h"

#include "array_method.h"                        /* Additional headers specific to implementation */
#include "common.h"
#include "numpy/npy_math.h"
#include "convert_datatype.h"
#include "dtypemeta.h"
#include "dispatching.h"
#include "gil_utils.h"
#include "multiarraymodule.h"

typedef struct {
    PyArray_Descr base;                         /* Define structure for scaled float descriptor */
    double scaling;                             /* Scaling factor for the float */
} PyArray_SFloatDescr;

static PyArray_DTypeMeta PyArray_SFloatDType;   /* Define DTypeMeta object for scaled float */
static PyArray_SFloatDescr SFloatSingleton;     /* Singleton instance of scaled float descriptor */


static int
sfloat_is_known_scalar_type(PyArray_DTypeMeta *NPY_UNUSED(cls), PyTypeObject *type)
{
    /* Check if the given type is a float type */
    if (type == &PyFloat_Type) {
        return 1;   /* Return true if it's a float */
    }
    return 0;       /* Otherwise, return false */
}


static PyArray_Descr *
sfloat_default_descr(PyArray_DTypeMeta *NPY_UNUSED(cls))
{
    Py_INCREF(&SFloatSingleton);   /* Increment reference count for the singleton descriptor */
    return (PyArray_Descr *)&SFloatSingleton;   /* Return the descriptor as PyArray_Descr* */
}


static PyArray_Descr *
sfloat_discover_from_pyobject(PyArray_DTypeMeta *cls, PyObject *NPY_UNUSED(obj))
{
    return sfloat_default_descr(cls);   /* Return the default descriptor for a given Python object */
}


static PyArray_DTypeMeta *
sfloat_common_dtype(PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
{
    /* Common dtype function to check compatibility with another dtype */
    if (NPY_DT_is_legacy(other) && other->type_num == NPY_DOUBLE) {
        Py_INCREF(cls);
        return cls;   /* Return self if the other dtype is legacy and double */
    }
    Py_INCREF(Py_NotImplemented);
    return (PyArray_DTypeMeta *)Py_NotImplemented;   /* Otherwise, return NotImplemented */
}


static PyArray_Descr *
sfloat_common_instance(PyArray_Descr *descr1, PyArray_Descr *descr2)
{
    PyArray_SFloatDescr *sf1 = (PyArray_SFloatDescr *)descr1;
    PyArray_SFloatDescr *sf2 = (PyArray_SFloatDescr *)descr2;
    /* Choose the descriptor with the larger scaling factor */
    if (sf1->scaling >= sf2->scaling) {
        Py_INCREF(descr1);
        return descr1;   /* Return the first descriptor if its scaling is larger or equal */
    }
    Py_INCREF(descr2);
    return descr2;       /* Otherwise, return the second descriptor */
}


/*
 * Implement minimal getitem and setitem to make this DType mostly(?) safe to
 * expose in Python.
 * TODO: This should not use the old-style API, but the new-style is missing!
*/

static PyObject *
sfloat_getitem(char *data, PyArrayObject *arr)
{
    PyArray_SFloatDescr *descr = (PyArray_SFloatDescr *)PyArray_DESCR(arr);
    double value;

    memcpy(&value, data, sizeof(double));   /* Copy the double value from data */
    return PyFloat_FromDouble(value * descr->scaling);   /* Return scaled float value */
}


static int
sfloat_setitem(PyObject *obj, char *data, PyArrayObject *arr)
{
    # 检查对象是否为精确的浮点数类型,如果不是则抛出异常并返回-1
    if (!PyFloat_CheckExact(obj)) {
        PyErr_SetString(PyExc_NotImplementedError,
                "Currently only accepts floats");
        return -1;
    }

    # 获取数组对象的浮点数描述符
    PyArray_SFloatDescr *descr = (PyArray_SFloatDescr *)PyArray_DESCR(arr);
    
    # 将Python浮点数对象转换为C语言的double类型值
    double value = PyFloat_AsDouble(obj);
    
    # 将值按描述符中的缩放因子进行缩放处理
    value /= descr->scaling;

    # 将处理后的double值复制到数据缓冲区中
    memcpy(data, &value, sizeof(double));
    
    # 操作成功完成,返回0表示成功
    return 0;
/* Special DType methods and the descr->f slot storage */

/* 定义结构体变量 sfloat_slots,包含一系列与特定数据类型相关的函数指针 */
NPY_DType_Slots sfloat_slots = {
    .discover_descr_from_pyobject = &sfloat_discover_from_pyobject,
    .is_known_scalar_type = &sfloat_is_known_scalar_type,
    .default_descr = &sfloat_default_descr,
    .common_dtype = &sfloat_common_dtype,
    .common_instance = &sfloat_common_instance,
    .f = {
        .getitem = (PyArray_GetItemFunc *)&sfloat_getitem,
        .setitem = (PyArray_SetItemFunc *)&sfloat_setitem,
    }
};

/* 定义静态变量 SFloatSingleton,描述浮点数类型的属性 */
static PyArray_SFloatDescr SFloatSingleton = {{
        .byteorder = '|',  /* 不需要处理字节顺序 */
        .flags = NPY_USE_GETITEM | NPY_USE_SETITEM,
        .type_num = -1,
        .elsize = sizeof(double),
        .alignment = NPY_ALIGNOF(double),
    },
    .scaling = 1,
};

/* 复制浮点数描述符并进行缩放 */
static PyArray_Descr *sfloat_scaled_copy(PyArray_SFloatDescr *self, double factor) {
    PyArray_SFloatDescr *new = PyObject_New(
            PyArray_SFloatDescr, (PyTypeObject *)&PyArray_SFloatDType);
    if (new == NULL) {
        return NULL;
    }
    /* 不复制 PyObject_HEAD 部分 */
    memcpy((char *)new + sizeof(PyObject),
            (char *)self + sizeof(PyObject),
            sizeof(PyArray_SFloatDescr) - sizeof(PyObject));

    new->scaling = new->scaling * factor;
    return (PyArray_Descr *)new;
}

/* Python 函数,用于复制浮点数类型并进行缩放 */
PyObject *python_sfloat_scaled_copy(PyArray_SFloatDescr *self, PyObject *arg)
{
    if (!PyFloat_Check(arg)) {
        PyErr_SetString(PyExc_TypeError,
                "Scaling factor must be a python float.");
        return NULL;
    }
    double factor = PyFloat_AsDouble(arg);

    return (PyObject *)sfloat_scaled_copy(self, factor);
}

/* 返回浮点数类型的 scaling 属性 */
static PyObject *sfloat_get_scaling(PyArray_SFloatDescr *self, PyObject *NPY_UNUSED(args))
{
    return PyFloat_FromDouble(self->scaling);
}

/* 返回浮点数类型的 __reduce__ 方法 */
static PyObject *sfloat___reduce__(PyArray_SFloatDescr *self)
{
    return Py_BuildValue("(O(d))", Py_TYPE(self), self->scaling);
}

/* 定义浮点数类型的方法表 */
PyMethodDef sfloat_methods[] = {
    {"scaled_by",
         (PyCFunction)python_sfloat_scaled_copy, METH_O,
        "Method to get a dtype copy with different scaling, mainly to "
        "avoid having to implement many ways to create new instances."},
    {"get_scaling",
        (PyCFunction)sfloat_get_scaling, METH_NOARGS, NULL},
    {"__reduce__",
       (PyCFunction)sfloat___reduce__, METH_NOARGS, NULL},
    {NULL, NULL, 0, NULL}
};

/* 创建新的浮点数类型对象 */
static PyObject *sfloat_new(PyTypeObject *NPY_UNUSED(cls), PyObject *args, PyObject *kwds)
{
    double scaling = 1.;
    static char *kwargs_strs[] = {"scaling", NULL};

    if (!PyArg_ParseTupleAndKeywords(
            args, kwds, "|d:_ScaledFloatTestDType", kwargs_strs, &scaling)) {
        return NULL;
    }
    if (scaling == 1.) {
        Py_INCREF(&SFloatSingleton);
        return (PyObject *)&SFloatSingleton;
    }
    return (PyObject *)sfloat_scaled_copy(&SFloatSingleton, scaling);
}

/* 返回浮点数类型对象的字符串表示 */
static PyObject *sfloat_repr(PyArray_SFloatDescr *self)
{
    PyObject *scaling = PyFloat_FromDouble(self->scaling);
    /* 返回浮点数类型的字符串表示,包含 scaling 属性 */

    return PyUnicode_FromFormat("<SFloatDescr with scaling %f>", self->scaling);
}
    # 如果 scaling 是空指针,则返回空指针
    if (scaling == NULL) {
        return NULL;
    }
    # 使用 PyUnicode_FromFormat 函数创建一个新的 Python Unicode 对象,
    # 格式化字符串为 "_ScaledFloatTestDType(scaling=%R)",其中 %R 是格式化参数,
    # 表示将 scaling 对象转换为相应的 Python 表示形式
    PyObject *res = PyUnicode_FromFormat(
            "_ScaledFloatTestDType(scaling=%R)", scaling);
    # 减少 scaling 对象的引用计数,因为在创建 res 后不再需要 scaling
    Py_DECREF(scaling);
    # 返回创建的 Unicode 对象 res
    return res;
}
    if (((PyArray_SFloatDescr *)loop_descrs[0])->scaling
            == ((PyArray_SFloatDescr *)loop_descrs[1])->scaling) {
        /* 检查两个描述符的 scaling 属性是否相同 */
        *view_offset = 0;
        // 如果相同,则视为只是一个视图,设置视图偏移为0
        return NPY_NO_CASTING;
    }
    else if (-((PyArray_SFloatDescr *)loop_descrs[0])->scaling
             == ((PyArray_SFloatDescr *)loop_descrs[1])->scaling) {
        /* 检查两个描述符的 scaling 属性是否互为相反数 */
        // 如果是相反数,则改变符号不会丢失精度
        return NPY_EQUIV_CASTING;
    }
    // 如果两者不是相同的 scaling 或者互为相反数
    /* 技术上讲,这不是一个安全的类型转换,因为可能会发生溢出或下溢 */
    // 返回同类别的类型转换,但不保证安全性
    return NPY_SAME_KIND_CASTING;
/*
 * Casting to and from doubles.
 *
 * To keep things interesting, we ONLY define the trivial cast with a factor
 * of 1.  All other casts have to be handled by the sfloat to sfloat cast.
 *
 * The casting machinery should optimize this step away normally, since we
 * flag the this is a view.
 */
static int
cast_float_to_from_sfloat(PyArrayMethod_Context *NPY_UNUSED(context),
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取数据的长度
    npy_intp N = dimensions[0];
    // 输入数据指针
    char *in = data[0];
    // 输出数据指针
    char *out = data[1];
    // 遍历数据并进行类型转换
    for (npy_intp i = 0; i < N; i++) {
        // 将输入的 double 类型数据复制给输出
        *(double *)out = *(double *)in;
        // 更新输入指针的位置
        in += strides[0];
        // 更新输出指针的位置
        out += strides[1];
    }
    // 返回成功状态
    return 0;
}


/*
 * Resolve descriptors for casting from float to sfloat and vice versa.
 */
static NPY_CASTING
float_to_from_sfloat_resolve_descriptors(
        PyArrayMethodObject *NPY_UNUSED(self),
        PyArray_DTypeMeta *dtypes[2],
        PyArray_Descr *NPY_UNUSED(given_descrs[2]),
        PyArray_Descr *loop_descrs[2],
        npy_intp *view_offset)
{
    // 为输入和输出的数据类型获取默认描述符
    loop_descrs[0] = NPY_DT_CALL_default_descr(dtypes[0]);
    if (loop_descrs[0] == NULL) {
        // 如果获取失败,返回错误状态
        return -1;
    }
    loop_descrs[1] = NPY_DT_CALL_default_descr(dtypes[1]);
    if (loop_descrs[1] == NULL) {
        // 如果获取失败,返回错误状态
        return -1;
    }
    // 设置视图偏移量为0
    *view_offset = 0;
    // 返回无需类型转换的状态
    return NPY_NO_CASTING;
}


/*
 * Cast from sfloat to boolean (for testing the logical functions).
 */
static int
cast_sfloat_to_bool(PyArrayMethod_Context *NPY_UNUSED(context),
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取数据的长度
    npy_intp N = dimensions[0];
    // 输入数据指针
    char *in = data[0];
    // 输出数据指针
    char *out = data[1];
    // 遍历数据并进行类型转换
    for (npy_intp i = 0; i < N; i++) {
        // 将输入的 double 类型数据转换为布尔类型后赋给输出
        *(npy_bool *)out = *(double *)in != 0;
        // 更新输入指针的位置
        in += strides[0];
        // 更新输出指针的位置
        out += strides[1];
    }
    // 返回成功状态
    return 0;
}

/*
 * Resolve descriptors for casting from sfloat to boolean.
 */
static NPY_CASTING
sfloat_to_bool_resolve_descriptors(
        PyArrayMethodObject *NPY_UNUSED(self),
        PyArray_DTypeMeta *NPY_UNUSED(dtypes[2]),
        PyArray_Descr *given_descrs[2],
        PyArray_Descr *loop_descrs[2],
        npy_intp *NPY_UNUSED(view_offset))
{
    // 增加对给定描述符的引用
    Py_INCREF(given_descrs[0]);
    // 设置输入描述符为给定的描述符
    loop_descrs[0] = given_descrs[0];
    if (loop_descrs[0] == NULL) {
        // 如果获取失败,返回错误状态
        return -1;
    }
    // 设置输出描述符为布尔类型的描述符(不可能失败)
    loop_descrs[1] = PyArray_DescrFromType(NPY_BOOL);  /* cannot fail */
    // 返回不安全类型转换状态
    return NPY_UNSAFE_CASTING;
}


/*
 * Initialize casting functions for sfloat.
 */
static int
sfloat_init_casts(void)
{
    // 定义输入和输出的数据类型为单精度浮点型
    PyArray_DTypeMeta *dtypes[2] = {&PyArray_SFloatDType, &PyArray_SFloatDType};
    // 初始化类型槽
    PyType_Slot slots[4] = {{0, NULL}};
    // 定义方法的规范
    PyArrayMethod_Spec spec = {
        .name = "sfloat_to_sfloat_cast",
        .nin = 1,
        .nout = 1,
        /* minimal guaranteed casting */
        .casting = NPY_SAME_KIND_CASTING,
        .flags = NPY_METH_SUPPORTS_UNALIGNED,
        .dtypes = dtypes,
        .slots = slots,
    };

    // 设置第一个槽位为解析描述符的方法
    slots[0].slot = NPY_METH_resolve_descriptors;
    slots[0].pfunc = &sfloat_to_sfloat_resolve_descriptors;

    // 设置第二个槽位为处理步进循环的方法
    slots[1].slot = NPY_METH_strided_loop;
    ```
    # 将第一个槽位的函数指针设置为 cast_sfloat_to_sfloat_aligned 函数的地址
    slots[1].pfunc = &cast_sfloat_to_sfloat_aligned;

    # 设置第二个槽位的标志为 NPY_METH_unaligned_strided_loop
    slots[2].slot = NPY_METH_unaligned_strided_loop;
    # 将第二个槽位的函数指针设置为 cast_sfloat_to_sfloat_unaligned 函数的地址
    slots[2].pfunc = &cast_sfloat_to_sfloat_unaligned;

    # 向 PyArray_AddCastingImplementation_FromSpec 函数添加类型转换规范
    if (PyArray_AddCastingImplementation_FromSpec(&spec, 0)) {
        return -1;
    }

    # 设置 spec 的名称为 "float_to_sfloat_cast"
    spec.name = "float_to_sfloat_cast";
    # 设置 spec 的标志为 NPY_METH_NO_FLOATINGPOINT_ERRORS
    spec.flags = NPY_METH_NO_FLOATINGPOINT_ERRORS;
    # 获取 PyArray_DoubleDType 的指针,并将其赋值给 dtypes 数组的第一个元素
    PyArray_DTypeMeta *double_DType = &PyArray_DoubleDType;
    dtypes[0] = double_DType;

    # 设置 slots 数组的各个槽位的值和函数指针,用于处理浮点到半浮点的转换
    slots[0].slot = NPY_METH_resolve_descriptors;
    slots[0].pfunc = &float_to_from_sfloat_resolve_descriptors;
    slots[1].slot = NPY_METH_strided_loop;
    slots[1].pfunc = &cast_float_to_from_sfloat;
    slots[2].slot = 0;
    slots[2].pfunc = NULL;

    # 再次向 PyArray_AddCastingImplementation_FromSpec 函数添加类型转换规范
    if (PyArray_AddCastingImplementation_FromSpec(&spec, 0)) {
        return -1;
    }

    # 设置 spec 的名称为 "sfloat_to_float_cast"
    spec.name = "sfloat_to_float_cast";
    # 设置 dtypes 数组的第一个元素为 PyArray_SFloatDType 的指针
    dtypes[0] = &PyArray_SFloatDType;
    # 设置 dtypes 数组的第二个元素为 double_DType 指针
    dtypes[1] = double_DType;

    # 再次向 PyArray_AddCastingImplementation_FromSpec 函数添加类型转换规范
    if (PyArray_AddCastingImplementation_FromSpec(&spec, 0)) {
        return -1;
    }

    # 设置 slots 数组的各个槽位的值和函数指针,用于处理半浮点到布尔型的转换
    slots[0].slot = NPY_METH_resolve_descriptors;
    slots[0].pfunc = &sfloat_to_bool_resolve_descriptors;
    slots[1].slot = NPY_METH_strided_loop;
    slots[1].pfunc = &cast_sfloat_to_bool;
    slots[2].slot = 0;
    slots[2].pfunc = NULL;

    # 设置 spec 的名称为 "sfloat_to_bool_cast"
    spec.name = "sfloat_to_bool_cast";
    # 设置 dtypes 数组的第一个元素为 PyArray_SFloatDType 的指针
    dtypes[0] = &PyArray_SFloatDType;
    # 设置 dtypes 数组的第二个元素为 PyArray_BoolDType 的指针
    dtypes[1] = &PyArray_BoolDType;

    # 再次向 PyArray_AddCastingImplementation_FromSpec 函数添加类型转换规范
    if (PyArray_AddCastingImplementation_FromSpec(&spec, 0)) {
        return -1;
    }

    # 返回 0 表示函数执行成功
    return 0;
/*
 * We also wish to test very simple ufunc functionality.  So create two
 * ufunc loops:
 * 1. Multiplication, which can multiply the factors and work with that.
 * 2. Addition, which needs to use the common instance, and runs into
 *    cast safety subtleties since we will implement it without an additional
 *    cast.
 */
static int
multiply_sfloats(PyArrayMethod_Context *NPY_UNUSED(context),
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取第一个维度的大小
    npy_intp N = dimensions[0];
    // 获取输入数组的指针
    char *in1 = data[0];
    char *in2 = data[1];
    // 获取输出数组的指针
    char *out = data[2];
    // 遍历数组进行乘法运算
    for (npy_intp i = 0; i < N; i++) {
        // 将输入数组中的双精度浮点数相乘,结果存入输出数组中
        *(double *)out = *(double *)in1 * *(double *)in2;
        // 更新输入数组和输出数组的指针位置
        in1 += strides[0];
        in2 += strides[1];
        out += strides[2];
    }
    return 0;
}


static NPY_CASTING
multiply_sfloats_resolve_descriptors(
        PyArrayMethodObject *NPY_UNUSED(self),
        PyArray_DTypeMeta *NPY_UNUSED(dtypes[3]),
        PyArray_Descr *given_descrs[3],
        PyArray_Descr *loop_descrs[3],
        npy_intp *NPY_UNUSED(view_offset))
{
    /*
     * Multiply the scaling for the result.  If the result was passed in we
     * simply ignore it and let the casting machinery fix it up here.
     */
    // 获取第一个输入描述符的缩放因子
    double factor = ((PyArray_SFloatDescr *)given_descrs[1])->scaling;
    // 创建新的输出描述符,使用第一个输入描述符和缩放因子
    loop_descrs[2] = sfloat_scaled_copy(
            (PyArray_SFloatDescr *)given_descrs[0], factor);
    // 检查是否成功创建新的输出描述符
    if (loop_descrs[2] == 0) {
        return -1;
    }
    // 增加输入描述符的引用计数
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    // 增加第二个输入描述符的引用计数
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];
    // 指定无需类型转换
    return NPY_NO_CASTING;
}


/*
 * Unlike the multiplication implementation above, this loops deals with
 * scaling (casting) internally.  This allows to test some different paths.
 */
static int
add_sfloats(PyArrayMethod_Context *context,
        char *const data[], npy_intp const dimensions[],
        npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata))
{
    // 获取第一个输入描述符的缩放因子
    double fin1 = ((PyArray_SFloatDescr *)context->descriptors[0])->scaling;
    // 获取第二个输入描述符的缩放因子
    double fin2 = ((PyArray_SFloatDescr *)context->descriptors[1])->scaling;
    // 获取输出描述符的缩放因子
    double fout = ((PyArray_SFloatDescr *)context->descriptors[2])->scaling;

    // 计算输入输出之间的缩放因子
    double fact1 = fin1 / fout;
    double fact2 = fin2 / fout;
    // 检查第一个缩放因子是否有效
    if (check_factor(fact1) < 0) {
        return -1;
    }
    // 检查第二个缩放因子是否有效
    if (check_factor(fact2) < 0) {
        return -1;
    }

    // 获取第一个维度的大小
    npy_intp N = dimensions[0];
    // 获取输入数组的指针
    char *in1 = data[0];
    char *in2 = data[1];
    // 获取输出数组的指针
    char *out = data[2];
    // 遍历数组进行加法运算
    for (npy_intp i = 0; i < N; i++) {
        // 将输入数组中的双精度浮点数按比例相加,结果存入输出数组中
        *(double *)out = (*(double *)in1 * fact1) + (*(double *)in2 * fact2);
        // 更新输入数组和输出数组的指针位置
        in1 += strides[0];
        in2 += strides[1];
        out += strides[2];
    }
    return 0;
}


static NPY_CASTING
/*
 * 根据给定的描述符解析添加单精度浮点数,并解决描述符。
 * 如果没有给定输出描述符,则使用常见实例。
 */
add_sfloats_resolve_descriptors(
        PyArrayMethodObject *NPY_UNUSED(self),
        PyArray_DTypeMeta *NPY_UNUSED(dtypes[3]),
        PyArray_Descr *given_descrs[3],
        PyArray_Descr *loop_descrs[3],
        npy_intp *NPY_UNUSED(view_offset))
{
    /*
     * 如果没有给定输出描述符,则使用常见实例:
     */
    if (given_descrs[2] == NULL) {
        // 使用给定的输入描述符创建一个共享的单精度浮点数描述符
        loop_descrs[2] = sfloat_common_instance(
                given_descrs[0], given_descrs[1]);
        if (loop_descrs[2] == 0) {
            return -1; // 失败返回
        }
    }
    else {
        // 增加引用计数以使用给定的输出描述符
        Py_INCREF(given_descrs[2]);
        loop_descrs[2] = given_descrs[2];
    }
    // 增加引用计数以使用给定的输入描述符
    Py_INCREF(given_descrs[0]);
    loop_descrs[0] = given_descrs[0];
    Py_INCREF(given_descrs[1]);
    loop_descrs[1] = given_descrs[1];

    /* 如果比例因子不匹配,我们在ufunc内部进行隐式转换! */
    double fin1 = ((PyArray_SFloatDescr *)loop_descrs[0])->scaling;
    double fin2 = ((PyArray_SFloatDescr *)loop_descrs[1])->scaling;
    double fout = ((PyArray_SFloatDescr *)loop_descrs[2])->scaling;

    // 如果输入和输出的比例因子完全匹配,则不需要转换
    if (fin1 == fout && fin2 == fout) {
        return NPY_NO_CASTING;
    }
    // 如果输入的绝对值和输出的绝对值相匹配,则可以进行等价转换
    if (npy_fabs(fin1) == npy_fabs(fout) && npy_fabs(fin2) == npy_fabs(fout)) {
        return NPY_EQUIV_CASTING;
    }
    // 否则,进行相同类型的转换
    return NPY_SAME_KIND_CASTING;
}


/*
 * 使用 "PyUFunc_AddWrappingLoop" API 定义 hypot 循环。
 * 目前仅用于映射到双精度 hypot 循环。
 */
static int
translate_given_descrs_to_double(
        int nin, int nout, PyArray_DTypeMeta *const wrapped_dtypes[],
        PyArray_Descr *const given_descrs[], PyArray_Descr *new_descrs[])
{
    assert(nin == 2 && nout == 1);
    for (int i = 0; i < 3; i++) {
        if (given_descrs[i] == NULL) {
            new_descrs[i] = NULL;
        }
        else {
            // 将给定的描述符转换为双精度描述符
            new_descrs[i] = PyArray_DescrFromType(NPY_DOUBLE);
        }
    }
    return 0;
}


/*
 * 将给定的描述符转换为循环描述符。
 */
static int
translate_loop_descrs(
        int nin, int nout, PyArray_DTypeMeta *const new_dtypes[],
        PyArray_Descr *const given_descrs[],
        PyArray_Descr *NPY_UNUSED(original_descrs[]),
        PyArray_Descr *loop_descrs[])
{
    assert(nin == 2 && nout == 1);
    // 使用给定的输入描述符创建共享的单精度浮点数描述符
    loop_descrs[0] = sfloat_common_instance(
            given_descrs[0], given_descrs[1]);
    if (loop_descrs[0] == 0) {
        return -1; // 失败返回
    }
    // 增加引用计数以使用共享的描述符
    Py_INCREF(loop_descrs[0]);
    loop_descrs[1] = loop_descrs[0];
    Py_INCREF(loop_descrs[0]);
    loop_descrs[2] = loop_descrs[0];
    return 0;
}


/*
 * 根据给定的 ufunc 名称获取 ufunc 对象。
 */
static PyObject *
sfloat_get_ufunc(const char *ufunc_name)
{
    // 导入 numpy 模块
    PyObject *mod = PyImport_ImportModule("numpy");
    if (mod == NULL) {
        return NULL; // 导入失败
    }
    // 获取指定名称的 ufunc 对象
    PyObject *ufunc = PyObject_GetAttrString(mod, ufunc_name);
    Py_DECREF(mod);
    // 检查获取的对象是否为 ufunc 类型
    if (!PyObject_TypeCheck(ufunc, &PyUFunc_Type)) {
        Py_DECREF(ufunc);
        // 如果不是 ufunc 类型,则抛出类型错误异常
        PyErr_Format(PyExc_TypeError,
                "numpy.%s was not a ufunc!", ufunc_name);
        return NULL;
    }
    // 返回获取到的 ufunc 对象
    return ufunc;
}
    # 返回 ufunc 变量的值
    return ufunc;
/*
 * Add a new loop to the specified ufunc for floating-point addition.
 * This function retrieves the ufunc object by name and prepares the necessary
 * information to add a new loop for the given data types.
 */
static int
sfloat_add_loop(const char *ufunc_name,
        PyArray_DTypeMeta *dtypes[3], PyObject *meth_or_promoter)
{
    // 获取指定名称的ufunc对象
    PyObject *ufunc = sfloat_get_ufunc(ufunc_name);
    if (ufunc == NULL) {
        return -1;
    }
    
    // 创建一个包含三个数据类型的元组
    PyObject *dtype_tup = PyArray_TupleFromItems(3, (PyObject **)dtypes, 1);
    if (dtype_tup == NULL) {
        Py_DECREF(ufunc);
        return -1;
    }
    
    // 打包类型元组和方法/推广器成为一个元组info
    PyObject *info = PyTuple_Pack(2, dtype_tup, meth_or_promoter);
    Py_DECREF(dtype_tup);
    if (info == NULL) {
        Py_DECREF(ufunc);
        return -1;
    }
    
    // 添加循环到ufunc对象中
    int res = PyUFunc_AddLoop((PyUFuncObject *)ufunc, info, 0);
    Py_DECREF(ufunc);
    Py_DECREF(info);
    return res;
}


/*
 * Add a wrapping loop to the specified ufunc for floating-point addition.
 * This function retrieves the ufunc object by name and adds a wrapping loop
 * using the provided data types and their corresponding wrapped versions.
 */
static int
sfloat_add_wrapping_loop(const char *ufunc_name, PyArray_DTypeMeta *dtypes[3])
{
    // 获取指定名称的ufunc对象
    PyObject *ufunc = sfloat_get_ufunc(ufunc_name);
    if (ufunc == NULL) {
        return -1;
    }
    
    // 准备包裹的数据类型为双精度浮点类型
    PyArray_DTypeMeta *double_dt = &PyArray_DoubleDType;
    PyArray_DTypeMeta *wrapped_dtypes[3] = {double_dt, double_dt, double_dt};
    
    // 添加包裹循环到ufunc对象中
    int res = PyUFunc_AddWrappingLoop(
        ufunc, dtypes, wrapped_dtypes, &translate_given_descrs_to_double,
        &translate_loop_descrs);
    Py_DECREF(ufunc);

    return res;
}


/*
 * Add promoters to convert normal floats to scaled floats.
 * This function is used to promote data types for multiplication operations.
 */
static int
promote_to_sfloat(PyUFuncObject *NPY_UNUSED(ufunc),
        PyArray_DTypeMeta *const NPY_UNUSED(dtypes[3]),
        PyArray_DTypeMeta *const signature[3],
        PyArray_DTypeMeta *new_dtypes[3])
{
    // 遍历每个数据类型,将其推广为单精度浮点类型
    for (int i = 0; i < 3; i++) {
        PyArray_DTypeMeta *new = &PyArray_SFloatDType;
        if (signature[i] != NULL) {
            new = signature[i];
        }
        Py_INCREF(new);
        new_dtypes[i] = new;
    }
    return 0;
}


/*
 * Initialize custom ufuncs for single-precision floating-point operations.
 * This function initializes and registers ufuncs for multiplication and addition
 * of single-precision floating-point numbers.
 */
static int
sfloat_init_ufuncs(void) {
    // 定义三个单精度浮点类型的数据类型元组
    PyArray_DTypeMeta *dtypes[3] = {
            &PyArray_SFloatDType, &PyArray_SFloatDType, &PyArray_SFloatDType};
    
    // 定义三个PyType_Slot槽
    PyType_Slot slots[3] = {{0, NULL}};
    
    // 定义一个PyArrayMethod_Spec结构体用于描述方法
    PyArrayMethod_Spec spec = {
        .nin = 2,
        .nout =1,
        .dtypes = dtypes,
        .slots = slots,
    };
    
    // 添加乘法方法的解析描述符和循环函数
    spec.name = "sfloat_multiply";
    spec.casting = NPY_NO_CASTING;
    slots[0].slot = NPY_METH_resolve_descriptors;
    slots[0].pfunc = &multiply_sfloats_resolve_descriptors;
    slots[1].slot = NPY_METH_strided_loop;
    slots[1].pfunc = &multiply_sfloats;
    
    // 创建一个PyBoundArrayMethodObject对象
    PyBoundArrayMethodObject *bmeth = PyArrayMethod_FromSpec_int(&spec, 0);
    if (bmeth == NULL) {
        return -1;
    }
    
    // 添加乘法方法的循环到ufunc对象中
    int res = sfloat_add_loop("multiply",
            bmeth->dtypes, (PyObject *)bmeth->method);
    Py_DECREF(bmeth);
    if (res < 0) {
        return -1;
    }
    
    // 添加加法方法的解析描述符和循环函数
    spec.name = "sfloat_add";
    spec.casting = NPY_SAME_KIND_CASTING;
    slots[0].slot = NPY_METH_resolve_descriptors;
    slots[0].pfunc = &add_sfloats_resolve_descriptors;
    slots[1].slot = NPY_METH_strided_loop;
    slots[1].pfunc = &add_sfloats;
    
    // 创建一个PyBoundArrayMethodObject对象
    bmeth = PyArrayMethod_FromSpec_int(&spec, 0);
    if (bmeth == NULL) {
        return -1;
    }
    
    // 添加加法方法的循环到ufunc对象中
    res = sfloat_add_loop("add",
            bmeth->dtypes, (PyObject *)bmeth->method);
    Py_DECREF(bmeth);
    if (res < 0) {
        return -1;
    }
    
    return 0;
}
    # 使用给定的规格创建一个整数类型的数组方法对象
    bmeth = PyArrayMethod_FromSpec_int(&spec, 0);
    if (bmeth == NULL) {
        return -1;
    }
    # 调用特定方法名称为"add"的浮点数加法循环,并传入方法对象的数据类型和方法对象本身作为参数
    res = sfloat_add_loop("add",
            bmeth->dtypes, (PyObject *)bmeth->method);
    # 减少方法对象的引用计数
    Py_DECREF(bmeth);
    if (res < 0) {
        return -1;
    }

    # 注意:如果类型的缩放因子可以为负数,则包装实际上不正确
    if (sfloat_add_wrapping_loop("hypot", dtypes) < 0) {
        return -1;
    }

    """
     * 为双精度乘法的两个方向添加提升器。
     """
    # 创建一个指向双精度数据类型的指针
    PyArray_DTypeMeta *double_DType = &PyArray_DoubleDType;

    # 创建一个包含提升到单精度浮点数、双精度和空指针的数据类型元数据数组
    PyArray_DTypeMeta *promoter_dtypes[3] = {
            &PyArray_SFloatDType, double_DType, NULL};

    # 创建一个新的 Python Capsule 对象,用于封装提升到单精度浮点数的函数
    PyObject *promoter = PyCapsule_New(
            &promote_to_sfloat, "numpy._ufunc_promoter", NULL);
    if (promoter == NULL) {
        return -1;
    }
    # 调用特定方法名称为"multiply"的浮点数乘法循环,并传入提升器的数据类型数组和提升器本身作为参数
    res = sfloat_add_loop("multiply", promoter_dtypes, promoter);
    if (res < 0) {
        Py_DECREF(promoter);
        return -1;
    }
    # 调整提升器的数据类型数组,反向传入参数,并再次调用浮点数乘法循环
    promoter_dtypes[0] = double_DType;
    promoter_dtypes[1] = &PyArray_SFloatDType;
    res = sfloat_add_loop("multiply", promoter_dtypes, promoter);
    # 减少提升器对象的引用计数
    Py_DECREF(promoter);
    if (res < 0) {
        return -1;
    }

    # 返回操作成功的标志
    return 0;
"""
/*
 * Python entry point, exported via `umathmodule.h` and `multiarraymodule.c`.
 * TODO: Should be moved when the necessary API is not internal anymore.
 */
"""

# 检查全局变量以确保未初始化时获取单精度浮点数据类型
NPY_NO_EXPORT PyObject *
get_sfloat_dtype(PyObject *NPY_UNUSED(mod), PyObject *NPY_UNUSED(args))
{
    if (npy_thread_unsafe_state.get_sfloat_dtype_initialized) {
        # 如果已经初始化,增加对单精度浮点数据类型的引用计数并返回它
        Py_INCREF(&PyArray_SFloatDType);
        return (PyObject *)&PyArray_SFloatDType;
    }

    # 将单精度浮点数据类型的基类设置为描述符类型
    PyArray_SFloatDType.super.ht_type.tp_base = &PyArrayDescr_Type;

    # 准备单精度浮点数据类型对象,如果失败则返回空指针
    if (PyType_Ready((PyTypeObject *)&PyArray_SFloatDType) < 0) {
        return NULL;
    }

    # 创建一个新的字典来存储类型的转换实现
    NPY_DT_SLOTS(&PyArray_SFloatDType)->castingimpls = PyDict_New();
    if (NPY_DT_SLOTS(&PyArray_SFloatDType)->castingimpls == NULL) {
        return NULL;
    }

    # 使用单精度浮点数据类型初始化一个新的 Python 对象
    PyObject *o = PyObject_Init(
            (PyObject *)&SFloatSingleton, (PyTypeObject *)&PyArray_SFloatDType);
    if (o == NULL) {
        return NULL;
    }

    # 初始化单精度浮点类型的类型转换
    if (sfloat_init_casts() < 0) {
        return NULL;
    }

    # 初始化单精度浮点类型的通用函数
    if (sfloat_init_ufuncs() < 0) {
        return NULL;
    }

    # 将状态标记为已初始化
    npy_thread_unsafe_state.get_sfloat_dtype_initialized = NPY_TRUE;
    # 返回单精度浮点数据类型对象
    return (PyObject *)&PyArray_SFloatDType;
}

.\numpy\numpy\_core\src\umath\_struct_ufunc_tests.c

/*
 * struct_ufunc_test.c
 * This is the C code for creating your own
 * NumPy ufunc for a structured array dtype.
 *
 * Details explaining the Python-C API can be found under
 * 'Extending and Embedding' and 'Python/C API' at
 * docs.python.org .
 */

// 定义一个静态函数,用于将三个 uint64 类型的数组相加
static void add_uint64_triplet(char **args,
                               npy_intp const *dimensions,
                               npy_intp const* steps,
                               void* data)
{
    npy_intp i;
    npy_intp is1=steps[0];  // 第一个输入数组的步长
    npy_intp is2=steps[1];  // 第二个输入数组的步长
    npy_intp os=steps[2];   // 输出数组的步长
    npy_intp n=dimensions[0];  // 数组的维度大小
    npy_uint64 *x, *y, *z;   // 定义指向输入和输出数组的指针

    char *i1=args[0];   // 第一个输入数组的起始地址
    char *i2=args[1];   // 第二个输入数组的起始地址
    char *op=args[2];   // 输出数组的起始地址

    for (i = 0; i < n; i++) {
        // 将输入数组的地址强制转换为 uint64 类型的指针
        x = (npy_uint64*)i1;
        y = (npy_uint64*)i2;
        z = (npy_uint64*)op;

        // 执行相加操作,并将结果存入输出数组
        z[0] = x[0] + y[0];
        z[1] = x[1] + y[1];
        z[2] = x[2] + y[2];

        // 更新输入和输出数组的地址,移动到下一个元素
        i1 += is1;
        i2 += is2;
        op += os;
    }
}

// 定义一个 Python 函数,用于注册自定义的 ufunc
static PyObject*
register_fail(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args))
{
    PyObject *add_triplet;   // 定义一个 PyObject 类型的对象,用于存储 ufunc
    PyObject *dtype_dict;    // 用于存储结构化数据类型的字典对象
    PyArray_Descr *dtype;    // 用于存储结构化数据类型的描述符
    PyArray_Descr *dtypes[3];  // 定义一个数组,存储三个结构化数据类型的描述符
    int retval;              // 用于存储函数调用返回值的变量

    // 创建一个 ufunc 对象,名称为 "add_triplet",无文档字符串
    add_triplet = PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, 2, 1,
                                    PyUFunc_None, "add_triplet",
                                    "add_triplet_docstring", 0);

    // 创建一个包含结构化数据类型信息的字典对象
    dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]",
                               "f0", "u8", "f1", "u8", "f2", "u8");
    // 将 dtype_dict 转换为 PyArray_Descr 结构,并存储在 dtype 中
    PyArray_DescrConverter(dtype_dict, &dtype);
    // 释放 dtype_dict 占用的内存
    Py_DECREF(dtype_dict);

    // 将 dtype 分别赋值给 dtypes 数组中的三个元素
    dtypes[0] = dtype;
    dtypes[1] = dtype;
    dtypes[2] = dtype;

    // 将 add_uint64_triplet 函数注册到 add_triplet ufunc 中
    retval = PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet,
                                dtype,
                                &add_uint64_triplet,
                                dtypes,
                                NULL);

    // 如果注册失败,则释放内存并返回 NULL
    if (retval < 0) {
        Py_DECREF(add_triplet);
        Py_DECREF(dtype);
        return NULL;
    }

    // 再次尝试注册,以确保成功
    retval = PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet,
                                dtype,
                                &add_uint64_triplet,
                                dtypes,
                                NULL);
    // 释放内存
    Py_DECREF(add_triplet);
    Py_DECREF(dtype);
    // 如果再次注册失败,则返回 NULL
    if (retval < 0) {
        return NULL;
    }
    // 注册成功,返回 Py_None
    Py_RETURN_NONE;
}

// 定义模块中的方法列表
static PyMethodDef StructUfuncTestMethods[] = {
    {"register_fail",
        register_fail,
        METH_NOARGS, NULL},  // 注册失败时调用的方法
    {NULL, NULL, 0, NULL}   // 方法列表结束
};

// 定义模块的结构体
static struct PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,   // 模块定义的头部初始化
    "_struct_ufunc_tests",   // 模块名称
    NULL,                    // 模块文档字符串
    -1,                      // 模块状态
    StructUfuncTestMethods,  // 模块中定义的方法列表
    NULL,                    // 模块的全局状态
    NULL,                    // 模块中的内存分配函数
    NULL,                    // 模块中的内存释放函数
    NULL                     // 模块中的状态清理函数
};

// 模块初始化函数
PyMODINIT_FUNC PyInit__struct_ufunc_tests(void)
{
    PyObject *m, *add_triplet, *d;

    // 创建一个新模块对象
    m = PyModule_Create(&moduledef);
    // 返回创建的模块对象
    return m;
}
    // 声明 PyObject 类型的变量 dtype_dict,用于存储描述符字典
    PyObject *dtype_dict;
    // 声明 PyArray_Descr 类型的变量 dtype,用于存储数组描述符
    PyArray_Descr *dtype;
    // 声明 PyArray_Descr 类型的数组 dtypes,用于存储多个数组描述符
    PyArray_Descr *dtypes[3];

    // 创建 Python 模块对象 m,使用给定的 moduledef 结构体
    m = PyModule_Create(&moduledef);

    // 如果创建模块失败,返回 NULL
    if (m == NULL) {
        return NULL;
    }

    // 导入 NumPy 的数组支持模块
    import_array();
    // 导入 NumPy 的数学函数支持模块
    import_umath();

    // 创建一个通用函数对象 add_triplet,用于执行三个输入操作数的特定功能
    add_triplet = PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, 2, 1,
                                    PyUFunc_None, "add_triplet",
                                    "add_triplet_docstring", 0);

    // 使用 Py_BuildValue 函数创建一个 Python 字典对象 dtype_dict,包含三个键值对
    dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]",
                               "f0", "u8", "f1", "u8", "f2", "u8");
    // 将 dtype_dict 转换为 PyArray_Descr 结构体,存储在 dtype 中
    PyArray_DescrConverter(dtype_dict, &dtype);
    // 释放 dtype_dict 对象的引用计数
    Py_DECREF(dtype_dict);

    // 将同一个 dtype 描述符分配给数组 dtypes 的所有三个元素
    dtypes[0] = dtype;
    dtypes[1] = dtype;
    dtypes[2] = dtype;

    // 将描述符 dtype 注册到通用函数 add_triplet 中,并指定用于每个操作数的描述符数组 dtypes
    PyUFunc_RegisterLoopForDescr((PyUFuncObject *)add_triplet,
                                dtype,
                                &add_uint64_triplet,
                                dtypes,
                                NULL);

    // 释放描述符 dtype 对象的引用计数
    Py_DECREF(dtype);
    // 获取模块 m 的字典对象
    d = PyModule_GetDict(m);

    // 将 add_triplet 对象添加到模块字典 d 中,键为 "add_triplet"
    PyDict_SetItemString(d, "add_triplet", add_triplet);
    // 释放 add_triplet 对象的引用计数
    Py_DECREF(add_triplet);
    // 返回创建的 Python 模块对象 m
    return m;
}


注释:


# 这是一个单独的右括号 '}',用于结束一个代码块或数据结构的定义。

.\numpy\numpy\_core\src\umath\_umath_tests.dispatch.c

/**
 * Testing the utilities of the CPU dispatcher
 *
 * @targets $werror baseline
 * SSE2 SSE41 AVX2
 * VSX VSX2 VSX3
 * NEON ASIMD ASIMDHP
 */

// 包含 Python 核心头文件
#define PY_SSIZE_T_CLEAN
#include <Python.h>

// 包含 NumPy 的 CPU 分发相关头文件
#include "npy_cpu_dispatch.h"
#include "numpy/utils.h" // NPY_TOSTRING

// 如果未禁用优化,则包含特定的优化测试分发头文件
#ifndef NPY_DISABLE_OPTIMIZATION
    #include "_umath_tests.dispatch.h"
#endif

// 声明并定义 CPU 分发相关函数和变量
NPY_CPU_DISPATCH_DECLARE(const char *_umath_tests_dispatch_func, (void))
NPY_CPU_DISPATCH_DECLARE(extern const char *_umath_tests_dispatch_var)
NPY_CPU_DISPATCH_DECLARE(void _umath_tests_dispatch_attach, (PyObject *list))

// 初始化 CPU 分发变量并定义相应函数
const char *NPY_CPU_DISPATCH_CURFX(_umath_tests_dispatch_var) = NPY_TOSTRING(NPY_CPU_DISPATCH_CURFX(var));
const char *NPY_CPU_DISPATCH_CURFX(_umath_tests_dispatch_func)(void)
{
    static const char *current = NPY_TOSTRING(NPY_CPU_DISPATCH_CURFX(func));
    return current;
}

// 将当前 CPU 分发函数名称添加到给定的 Python 列表中
void NPY_CPU_DISPATCH_CURFX(_umath_tests_dispatch_attach)(PyObject *list)
{
    PyObject *item = PyUnicode_FromString(NPY_TOSTRING(NPY_CPU_DISPATCH_CURFX(func)));
    if (item) {
        PyList_Append(list, item);
        Py_DECREF(item);
    }
}

.\numpy\numpy\_core\src\_simd\_simd.c

#include "_simd.h"

#include "numpy/npy_math.h"

// 定义函数:获取当前浮点状态的 Python 对象
static PyObject *
get_floatstatus(PyObject* NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
{
    // 调用 numpy 库函数获取当前浮点状态并返回相应的 Python 对象
    return PyLong_FromLong(npy_get_floatstatus());
}

// 定义函数:清除当前浮点状态
static PyObject *
clear_floatstatus(PyObject* NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
{
    // 调用 numpy 库函数清除当前浮点状态
    npy_clear_floatstatus();
    // 直接返回 None 对象
    Py_RETURN_NONE;
}

// 定义模块方法列表
static PyMethodDef _simd_methods[] = {
    {"get_floatstatus", get_floatstatus, METH_NOARGS, NULL},  // 注册获取浮点状态函数
    {"clear_floatstatus", clear_floatstatus, METH_NOARGS, NULL},  // 注册清除浮点状态函数
    {NULL, NULL, 0, NULL}  // 结束方法列表的标记
};

// 模块初始化函数
PyMODINIT_FUNC PyInit__simd(void)
{
    // 定义模块结构体
    static struct PyModuleDef defs = {
        .m_base = PyModuleDef_HEAD_INIT,  // 设置模块结构的基本属性
        .m_name = "numpy._core._simd",  // 模块名称
        .m_size = -1,  // 模块大小
        .m_methods = _simd_methods  // 模块方法列表
    };

    // 初始化 CPU 相关功能,若失败则返回 NULL
    if (npy_cpu_init() < 0) {
        return NULL;
    }

    // 创建 Python 模块对象,如果失败则返回 NULL
    PyObject *m = PyModule_Create(&defs);
    if (m == NULL) {
        return NULL;
    }

    // 创建一个空的字典对象用于存储目标特性
    PyObject *targets = PyDict_New();
    if (targets == NULL) {
        goto err;  // 如果创建失败则跳转到错误处理
    }

    // 将 targets 字典对象添加到模块中,如果失败则释放 targets 并跳转到错误处理
    if (PyModule_AddObject(m, "targets", targets) < 0) {
        Py_DECREF(targets);
        goto err;
    }

    // 宏定义,用于根据特性测试情况添加模块
    #define ATTACH_MODULE(TESTED_FEATURES, TARGET_NAME, MAKE_MSVC_HAPPY)       \
        {                                                                      \
            PyObject *simd_mod;                                                \
            if (!TESTED_FEATURES) {                                            \
                Py_INCREF(Py_None);                                            \
                simd_mod = Py_None;                                            \
            } else {                                                           \
                simd_mod = NPY_CAT(simd_create_module_, TARGET_NAME)();        \
                if (simd_mod == NULL) {                                        \
                    goto err;                                                  \
                }                                                              \
            }                                                                  \
            const char *target_name = NPY_TOSTRING(TARGET_NAME);               \
            if (PyDict_SetItemString(targets, target_name, simd_mod) < 0) {    \
                Py_DECREF(simd_mod);                                           \
                goto err;                                                      \
            }                                                                  \
            Py_INCREF(simd_mod);                                               \
            if (PyModule_AddObject(m, target_name, simd_mod) < 0) {            \
                Py_DECREF(simd_mod);                                           \
                goto err;                                                      \
            }                                                                  \
        }

    // ATTACH_MODULE 宏的作用是根据特性情况添加模块对象到 targets 字典和模块中

    // 返回创建的模块对象
    return m;

// 错误处理代码块
err:
    // 在错误处理时释放所有已分配的资源,并返回 NULL
    Py_XDECREF(m);
    return NULL;
}
    #define ATTACH_BASELINE_MODULE(MAKE_MSVC_HAPPY)                            \
        {                                                                      \
            // 创建名为 baseline 的 Python 模块对象
            PyObject *simd_mod = simd_create_module();                         \
            // 如果创建失败,则跳转到错误处理标签 err
            if (simd_mod == NULL) {                                            \
                goto err;                                                      \
            }                                                                  \
            // 将 baseline 模块对象添加到 targets 字典中,如果失败则跳转到 err
            if (PyDict_SetItemString(targets, "baseline", simd_mod) < 0) {     \
                Py_DECREF(simd_mod);                                           \
                goto err;                                                      \
            }                                                                  \
            // 增加 baseline 模块对象的引用计数
            Py_INCREF(simd_mod);                                               \
            // 将 baseline 模块对象添加到 m 模块中,如果失败则跳转到 err
            if (PyModule_AddObject(m, "baseline", simd_mod) < 0) {             \
                Py_DECREF(simd_mod);                                           \
                goto err;                                                      \
            }                                                                  \
        }
    #ifdef NPY__CPU_MESON_BUILD
        // 使用 NPY_MTARGETS_CONF_DISPATCH 宏调用 ATTACH_MODULE 宏和 MAKE_MSVC_HAPPY 宏
        NPY_MTARGETS_CONF_DISPATCH(NPY_CPU_HAVE, ATTACH_MODULE, MAKE_MSVC_HAPPY)
        // 使用 NPY_MTARGETS_CONF_BASELINE 宏调用 ATTACH_BASELINE_MODULE 宏和 MAKE_MSVC_HAPPY 宏
        NPY_MTARGETS_CONF_BASELINE(ATTACH_BASELINE_MODULE, MAKE_MSVC_HAPPY)
    #else
        // 使用 NPY__CPU_DISPATCH_CALL 宏调用 ATTACH_MODULE 宏和 MAKE_MSVC_HAPPY 宏
        NPY__CPU_DISPATCH_CALL(NPY_CPU_HAVE, ATTACH_MODULE, MAKE_MSVC_HAPPY)
        // 使用 NPY__CPU_DISPATCH_BASELINE_CALL 宏调用 ATTACH_BASELINE_MODULE 宏和 MAKE_MSVC_HAPPY 宏
        NPY__CPU_DISPATCH_BASELINE_CALL(ATTACH_BASELINE_MODULE, MAKE_MSVC_HAPPY)
    #endif
    // 返回模块对象 m
    return m;
err:
    # 减少 Python 对象 m 的引用计数,释放其占用的内存
    Py_DECREF(m);
    # 返回 NULL 表示函数执行失败
    return NULL;
}

.\numpy\numpy\_core\src\_simd\_simd.h

/**
 * A module to expose the NumPy C SIMD vectorization interface "NPYV" for testing purposes.
 *
 * Please keep this module independent from other c-extension modules,
 * since NPYV intrinsics may be involved in their functionality,
 * which increases the degree of complexity in tracking and detecting errors.
 *
 * TODO: Add an independent sphinx doc.
 *
 * Please add any new NPYV intrinsics in '_simd.dispatch.c.src'.
 */
#ifndef _SIMD_SIMD_H_
#define _SIMD_SIMD_H_

#include <Python.h>
#include "numpy/npy_common.h"
#include "npy_cpu_features.h"
#include "npy_cpu_dispatch.h"
#include "numpy/npy_cpu.h"

#ifndef NPY_DISABLE_OPTIMIZATION
// autogenerated, required for CPU dispatch macros
#include "_simd.dispatch.h"
#endif

/**
 * Declare a hidden visibility function 'simd_create_module' to create a new module
 * for each required optimization which contains all NPYV intrinsics.
 *
 * If a required optimization is not supported by NPYV, the module still provides
 * access to NPYV constants NPY_SIMD, NPY_SIMD_F64, and NPY_SIMD_WIDTH but without
 * any intrinsics.
 */
NPY_CPU_DISPATCH_DECLARE(NPY_VISIBILITY_HIDDEN PyObject *simd_create_module, (void))

#endif // _SIMD_SIMD_H_

.\numpy\numpy\_core\strings.py

"""
This module contains a set of functions for vectorized string
operations.
"""

import sys
import numpy as np
from numpy import (
    equal, not_equal, less, less_equal, greater, greater_equal,
    add, multiply as _multiply_ufunc,
)
from numpy._core.multiarray import _vec_string
from numpy._core.umath import (
    isalpha,
    isdigit,
    isspace,
    isalnum,
    islower,
    isupper,
    istitle,
    isdecimal,
    isnumeric,
    str_len,
    find as _find_ufunc,
    rfind as _rfind_ufunc,
    index as _index_ufunc,
    rindex as _rindex_ufunc,
    count as _count_ufunc,
    startswith as _startswith_ufunc,
    endswith as _endswith_ufunc,
    _lstrip_whitespace,
    _lstrip_chars,
    _rstrip_whitespace,
    _rstrip_chars,
    _strip_whitespace,
    _strip_chars,
    _replace,
    _expandtabs_length,
    _expandtabs,
    _center,
    _ljust,
    _rjust,
    _zfill,
    _partition,
    _partition_index,
    _rpartition,
    _rpartition_index,
)

# Exported symbols from this module
__all__ = [
    # UFuncs
    "equal", "not_equal", "less", "less_equal", "greater", "greater_equal",
    "add", "multiply", "isalpha", "isdigit", "isspace", "isalnum", "islower",
    "isupper", "istitle", "isdecimal", "isnumeric", "str_len", "find",
    "rfind", "index", "rindex", "count", "startswith", "endswith", "lstrip",
    "rstrip", "strip", "replace", "expandtabs", "center", "ljust", "rjust",
    "zfill", "partition", "rpartition",

    # _vec_string - Will gradually become ufuncs as well
    "upper", "lower", "swapcase", "capitalize", "title",

    # _vec_string - Will probably not become ufuncs
    "mod", "decode", "encode", "translate",

    # Removed from namespace until behavior has been crystalized
    # "join", "split", "rsplit", "splitlines",
]

# Maximum value for int64 data type
MAX = np.iinfo(np.int64).max


def _get_num_chars(a):
    """
    Helper function that returns the number of characters per field in
    a string or unicode array.  This is to abstract out the fact that
    for a unicode array this is itemsize / 4.
    """
    if issubclass(a.dtype.type, np.str_):
        # For numpy string arrays, calculate number of characters per field
        return a.itemsize // 4
    # For other types, return the itemsize
    return a.itemsize


def _to_bytes_or_str_array(result, output_dtype_like):
    """
    Helper function to cast a result back into an array
    with the appropriate dtype if an object array must be used
    as an intermediary.
    """
    # Convert output_dtype_like to numpy array
    output_dtype_like = np.asarray(output_dtype_like)
    if result.size == 0:
        # If result is empty, convert directly to output_dtype_like's dtype
        return result.astype(output_dtype_like.dtype)
    # Convert result to numpy array, considering output_dtype_like's dtype
    ret = np.asarray(result.tolist())
    if isinstance(output_dtype_like.dtype, np.dtypes.StringDType):
        # If output_dtype_like is string type, cast ret accordingly
        return ret.astype(type(output_dtype_like.dtype))
    # Otherwise, cast ret based on output_dtype_like's dtype and itemsize
    return ret.astype(type(output_dtype_like.dtype)(_get_num_chars(ret)))


def _clean_args(*args):
    """
    Helper function for delegating arguments to Python string
    functions.

    Many of the Python string operations that have optional arguments
    are handled by this function.
    """
    # 创建一个空列表,用于存储处理后的参数
    newargs = []
    # 遍历传入的参数列表 args
    for chk in args:
        # 如果当前参数是 None,则停止遍历
        if chk is None:
            break
        # 将非 None 的参数添加到新的参数列表 newargs 中
        newargs.append(chk)
    # 返回处理后的参数列表 newargs
    return newargs
# 定义一个函数,用于实现字符串的多重拼接操作,即将数组 `a` 中的每个元素与数组 `i` 中对应位置的整数倍拼接成新的字符串数组。

def multiply(a, i):
    """
    Return (a * i), that is string multiple concatenation,
    element-wise.

    Values in ``i`` of less than 0 are treated as 0 (which yields an
    empty string).

    Parameters
    ----------
    a : array_like, with ``StringDType``, ``bytes_`` or ``str_`` dtype
        Input array containing strings or bytes to be multiplied.

    i : array_like, with any integer dtype
        Input array containing integers representing the number of times
        each string in `a` should be repeated.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types. Contains the result of element-wise
        string multiplication.

    Raises
    ------
    TypeError
        If `i` contains a dtype that is not an integer.

    MemoryError
        If the resulting repeated strings exceed system memory.

    Examples
    --------
    Provides examples of how the function operates with different inputs.
    """
    # 将输入的 `a` 和 `i` 转换为 NumPy 数组
    a = np.asanyarray(a)
    i = np.asanyarray(i)
    
    # 检查 `i` 是否为整数类型,若不是则抛出类型错误
    if not np.issubdtype(i.dtype, np.integer):
        raise TypeError(f"unsupported type {i.dtype} for operand 'i'")
    
    # 将 `i` 中小于 0 的值设为 0,确保不会产生空字符串
    i = np.maximum(i, 0)

    # 如果 `a` 的 dtype 是 'T',即字符串类型,则直接使用乘法操作
    if a.dtype.char == "T":
        return a * i

    # 计算 `a` 中每个字符串的长度
    a_len = str_len(a)

    # 确保进行字符串拼接不会导致内存溢出
    if np.any(a_len > sys.maxsize / np.maximum(i, 1)):
        raise MemoryError("repeated string is too long")

    # 计算拼接后的字符串数组的长度
    buffersizes = a_len * i

    # 创建一个与 `a` 类型相同、形状为 `buffersizes.shape`、dtype 为 `out_dtype` 的空数组
    out_dtype = f"{a.dtype.char}{buffersizes.max()}"
    out = np.empty_like(a, shape=buffersizes.shape, dtype=out_dtype)

    # 调用内部函数 `_multiply_ufunc` 完成实际的拼接操作
    return _multiply_ufunc(a, i, out=out)


# 定义一个函数,实现字符串格式化操作,即将数组 `a` 中的每个元素与数组 `values` 中对应位置的值进行格式化插入。

def mod(a, values):
    """
    Return (a % i), that is pre-Python 2.6 string formatting
    (interpolation), element-wise for a pair of array_likes of str
    or unicode.

    Parameters
    ----------
    a : array_like, with `np.bytes_` or `np.str_` dtype
        Input array containing strings or bytes to be formatted.

    values : array_like of values
       These values will be element-wise interpolated into the string.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types. Contains the result of element-wise
        string formatting.
    """
    # 调用 `_vec_string` 函数进行字符串格式化操作,最终返回格式化后的数组
    return _to_bytes_or_str_array(
        _vec_string(a, np.object_, '__mod__', (values,)), a)


# 定义一个函数,用于在数组 `a` 中的每个元素中查找子字符串 `sub`,返回子字符串在每个元素中第一次出现的索引位置。

def find(a, sub, start=0, end=None):
    """
    For each element, return the lowest index in the string where
    substring ``sub`` is found, such that ``sub`` is contained in the
    range [``start``, ``end``).

    Parameters
    ----------
    a : array_like, with ``StringDType``, ``bytes_`` or ``str_`` dtype
        Input array containing strings or bytes to search within.

    sub : array_like, with `np.bytes_` or `np.str_` dtype
        The substring to search for.

    start, end : array_like, with any integer dtype, optional
        The range to look in, interpreted as in slice notation.

    Returns
    -------

    """

    # 返回一个包含每个元素中子字符串 `sub` 第一次出现的最低索引位置的数组
    return _vec_string(a, sub, 'find', (start, end))
    -------
    y : ndarray
        Output array of ints
    输出整数数组 `y`

    See Also
    --------
    str.find
    相关函数:str.find

    Examples
    --------
    >>> a = np.array(["NumPy is a Python library"])
    >>> np.strings.find(a, "Python")
    array([11])
    示例:在数组 `a` 中查找子字符串 "Python",返回位置索引数组 [11]

    """
    end = end if end is not None else MAX
    # 如果 `end` 不为 None,则使用 `end`;否则使用预定义的 `MAX` 值
    return _find_ufunc(a, sub, start, end)
    # 调用 `_find_ufunc` 函数,传递参数 `a`, `sub`, `start`, `end`,并返回其结果
# 返回数组中每个元素中指定子字符串最后出现的索引位置,查找范围为[start, end)。
def rfind(a, sub, start=0, end=None):
    end = end if end is not None else MAX  # 如果未提供end参数,则使用默认值MAX
    return _rfind_ufunc(a, sub, start, end)  # 调用内部的rfind函数进行实际查找


# 类似于find,但在子字符串未找到时引发ValueError异常。
def index(a, sub, start=0, end=None):
    end = end if end is not None else MAX  # 如果未提供end参数,则使用默认值MAX
    return _index_ufunc(a, sub, start, end)  # 调用内部的index函数进行实际查找


# 类似于rfind,但在子字符串未找到时引发ValueError异常。
def rindex(a, sub, start=0, end=None):
    end = end if end is not None else MAX  # 如果未提供end参数,则使用默认值MAX
    return _rindex_ufunc(a, sub, start, end)  # 调用内部的rindex函数进行实际查找


# 返回数组中每个元素中指定子字符串出现的非重叠次数,查找范围为[start, end)。
def count(a, sub, start=0, end=None):
    end = end if end is not None else MAX  # 如果未提供end参数,则使用默认值MAX
    return _count_ufunc(a, sub, start, end)  # 调用内部的count函数进行实际计数
    # 使用 numpy 库中的字符串处理函数 np.strings.count 对输入的字符串数组进行计数操作
    array([3, 1, 1])
    # 对字符串数组 c 中的每个字符串计算包含 'aA' 的次数,返回结果数组
    >>> np.strings.count(c, 'aA')
    array([3, 1, 0])
    # 对字符串数组 c 中的每个字符串,在指定范围 [start, end) 内计算包含 'A' 的次数,返回结果数组
    >>> np.strings.count(c, 'A', start=1, end=4)
    array([2, 1, 1])
    # 对字符串数组 c 中的每个字符串,在指定范围 [start, end) 内计算包含 'A' 的次数,返回结果数组
    >>> np.strings.count(c, 'A', start=1, end=3)
    # 如果 end 未指定,则使用预定义的 MAX 值作为结束位置
    array([1, 0, 0])

    """
    # 调用内部函数 _count_ufunc,传入参数 a, sub, start, end,并返回其结果
    end = end if end is not None else MAX
    return _count_ufunc(a, sub, start, end)
# 检查字符串数组中每个元素是否以指定前缀开头,返回布尔数组
def startswith(a, prefix, start=0, end=None):
    """
    Returns a boolean array which is `True` where the string element
    in ``a`` starts with ``prefix``, otherwise `False`.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入数组,元素可以是字符串类型,字节类型或者字符串

    prefix : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        要检查的前缀,可以是字符串类型,字节类型或者字符串

    start, end : array_like, with any integer dtype
        开始和结束位置的索引,用于指定检查的范围

    Returns
    -------
    out : ndarray
        布尔类型的输出数组,表示每个元素是否以指定前缀开头

    See Also
    --------
    str.startswith
        Python 内置函数 str.startswith 的文档参考

    """
    end = end if end is not None else MAX  # 如果未指定 end 参数,则使用默认值 MAX
    return _startswith_ufunc(a, prefix, start, end)


# 检查字符串数组中每个元素是否以指定后缀结尾,返回布尔数组
def endswith(a, suffix, start=0, end=None):
    """
    Returns a boolean array which is `True` where the string element
    in ``a`` ends with ``suffix``, otherwise `False`.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入数组,元素可以是字符串类型,字节类型或者字符串

    suffix : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        要检查的后缀,可以是字符串类型,字节类型或者字符串

    start, end : array_like, with any integer dtype
        开始和结束位置的索引,用于指定检查的范围

    Returns
    -------
    out : ndarray
        布尔类型的输出数组,表示每个元素是否以指定后缀结尾

    See Also
    --------
    str.endswith
        Python 内置函数 str.endswith 的文档参考

    Examples
    --------
    示例用法演示如何使用 np.strings.endswith 函数:
    >>> s = np.array(['foo', 'bar'])
    >>> s
    array(['foo', 'bar'], dtype='<U3')
    >>> np.strings.endswith(s, 'ar')
    array([False,  True])
    >>> np.strings.endswith(s, 'a', start=1, end=2)
    array([False,  True])

    """
    end = end if end is not None else MAX  # 如果未指定 end 参数,则使用默认值 MAX
    return _endswith_ufunc(a, suffix, start, end)


# 对字节数组进行解码,返回相应的字符串数组
def decode(a, encoding=None, errors=None):
    r"""
    Calls :meth:`bytes.decode` element-wise.

    The set of available codecs comes from the Python standard library,
    and may be extended at runtime.  For more information, see the
    :mod:`codecs` module.

    Parameters
    ----------
    a : array_like, with ``bytes_`` dtype
        输入数组,元素必须是字节类型

    encoding : str, optional
       字符串编码的名称,可选参数

    errors : str, optional
       指定如何处理解码错误的字符串,可选参数

    Returns
    -------
    out : ndarray
        解码后的字符串数组

    See Also
    --------
    :py:meth:`bytes.decode`
        Python 内置函数 bytes.decode 的文档参考

    Notes
    -----
    结果的数据类型取决于指定的编码格式。

    Examples
    --------
    示例用法演示如何使用 np.strings.decode 函数:
    >>> c = np.array([b'\x81\xc1\x81\xc1\x81\xc1', b'@@\x81\xc1@@',
    ...               b'\x81\x82\xc2\xc1\xc2\x82\x81'])
    >>> c
    array([b'\x81\xc1\x81\xc1\x81\xc1', b'@@\x81\xc1@@',
           b'\x81\x82\xc2\xc1\xc2\x82\x81'], dtype='|S7')
    >>> np.strings.decode(c, encoding='cp037')
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')

    """
    return _to_bytes_or_str_array(
        _vec_string(a, np.object_, 'decode', _clean_args(encoding, errors)),
        np.str_(''))
    Calls :meth:`str.encode` element-wise.
    # 调用 `str.encode` 方法对每个元素进行编码操作。

    The set of available codecs comes from the Python standard library,
    and may be extended at runtime. For more information, see the
    :mod:`codecs` module.
    # 可用的编解码器集合来自于 Python 标准库,并且可以在运行时进行扩展。有关更多信息,请参见 `codecs` 模块。

    Parameters
    ----------
    a : array_like, with ``StringDType`` or ``str_`` dtype
    # 参数 `a`:类似数组,其元素可以是 `StringDType` 或 `str_` 类型。

    encoding : str, optional
       The name of an encoding
    # 参数 `encoding`:字符串,可选,表示要使用的编码名称。

    errors : str, optional
       Specifies how to handle encoding errors
    # 参数 `errors`:字符串,可选,指定如何处理编码错误。

    Returns
    -------
    out : ndarray
    # 返回值 `out`:返回一个 NumPy 数组。

    See Also
    --------
    str.encode
    # 参见:`str.encode`

    Notes
    -----
    The type of the result will depend on the encoding specified.
    # 返回结果的类型取决于指定的编码。

    Examples
    --------
    >>> a = np.array(['aAaAaA', '  aA  ', 'abBABba'])
    >>> np.strings.encode(a, encoding='cp037')
    array([b'\x81\xc1\x81\xc1\x81\xc1', b'@@\x81\xc1@@',
       b'\x81\x82\xc2\xc1\xc2\x82\x81'], dtype='|S7')
    # 示例:对数组 `a` 中的字符串进行编码,使用编码器 `cp037`,返回编码后的 NumPy 数组。
       
    """
    return _to_bytes_or_str_array(
        _vec_string(a, np.object_, 'encode', _clean_args(encoding, errors)),
        np.bytes_(b''))
    # 调用 `_vec_string` 函数,对数组 `a` 的每个元素进行编码,返回字节或字符串数组。
    # `_clean_args` 函数用于清理并处理编码和错误处理参数。
    # 最终返回一个字节类型的 NumPy 数组。
# 将函数定义为一个名为 expandtabs 的函数,用于处理数组中的字符串元素,将其中的制表符替换为一定数量的空格
def expandtabs(a, tabsize=8):
    """
    Return a copy of each string element where all tab characters are
    replaced by one or more spaces.

    Calls :meth:`str.expandtabs` element-wise.

    Return a copy of each string element where all tab characters are
    replaced by one or more spaces, depending on the current column
    and the given `tabsize`. The column number is reset to zero after
    each newline occurring in the string. This doesn't understand other
    non-printing characters or escape sequences.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array
    tabsize : int, optional
        Replace tabs with `tabsize` number of spaces.  If not given defaults
        to 8 spaces.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input type

    See Also
    --------
    str.expandtabs

    Examples
    --------
    >>> a = np.array(['\t\tHello\tworld'])
    >>> np.strings.expandtabs(a, tabsize=4)  # doctest: +SKIP
    array(['        Hello   world'], dtype='<U21')  # doctest: +SKIP

    """
    # 将输入的 a 转换为 numpy 数组
    a = np.asanyarray(a)
    # 将输入的 tabsize 转换为 numpy 数组
    tabsize = np.asanyarray(tabsize)

    # 如果 a 的 dtype 是 "T" 类型
    if a.dtype.char == "T":
        # 调用内部函数 _expandtabs 处理 a
        return _expandtabs(a, tabsize)

    # 计算每个字符串元素经过扩展后的长度
    buffersizes = _expandtabs_length(a, tabsize)
    # 构造输出的 dtype,长度为 buffersizes 中的最大值
    out_dtype = f"{a.dtype.char}{buffersizes.max()}"
    # 创建一个和 a 相同形状的空数组,dtype 为 out_dtype
    out = np.empty_like(a, shape=buffersizes.shape, dtype=out_dtype)
    # 调用 _expandtabs 函数处理 a,并将结果写入 out 中
    return _expandtabs(a, tabsize, out=out)



# 将函数定义为一个名为 center 的函数,用于将数组中的字符串元素居中显示,可指定填充字符和输出宽度
def center(a, width, fillchar=' '):
    """
    Return a copy of `a` with its elements centered in a string of
    length `width`.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype

    width : array_like, with any integer dtype
        The length of the resulting strings, unless ``width < str_len(a)``.
    fillchar : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Optional padding character to use (default is space).

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.center

    Notes
    -----
    While it is possible for ``a`` and ``fillchar`` to have different dtypes,
    passing a non-ASCII character in ``fillchar`` when ``a`` is of dtype "S"
    is not allowed, and a ``ValueError`` is raised.

    Examples
    --------
    >>> c = np.array(['a1b2','1b2a','b2a1','2a1b']); c
    array(['a1b2', '1b2a', 'b2a1', '2a1b'], dtype='<U4')
    >>> np.strings.center(c, width=9)
    array(['   a1b2  ', '   1b2a  ', '   b2a1  ', '   2a1b  '], dtype='<U9')
    >>> np.strings.center(c, width=9, fillchar='*')
    array(['***a1b2**', '***1b2a**', '***b2a1**', '***2a1b**'], dtype='<U9')
    >>> np.strings.center(c, width=1)
    array(['a1b2', '1b2a', 'b2a1', '2a1b'], dtype='<U4')

    """
    # 将输入的 a 转换为 numpy 数组
    a = np.asanyarray(a)
    # 将 fillchar 转换为与 a 的数据类型相同的 NumPy 数组
    fillchar = np.asanyarray(fillchar, dtype=a.dtype)
    
    # 检查 fillchar 是否包含多个字符,如果是,则引发 TypeError 异常
    if np.any(str_len(fillchar) != 1):
        raise TypeError(
            "The fill character must be exactly one character long")
    
    # 如果 a 的数据类型为 'T'(字符串类型),则调用 _center 函数进行居中处理并返回结果
    if a.dtype.char == "T":
        return _center(a, width, fillchar)
    
    # 计算 a 的字符串长度与指定宽度的最大值,并用于输出的数据类型
    width = np.maximum(str_len(a), width)
    out_dtype = f"{a.dtype.char}{width.max()}"
    
    # 根据 a 的形状、指定宽度的形状和 fillchar 的形状,确定输出数组的形状
    shape = np.broadcast_shapes(a.shape, width.shape, fillchar.shape)
    
    # 创建一个与 a 类型相同的空数组,用于存储结果,并指定其形状和数据类型
    out = np.empty_like(a, shape=shape, dtype=out_dtype)
    
    # 调用 _center 函数,将 a、width、fillchar 和输出数组 out 传递给它,并返回结果
    return _center(a, width, fillchar, out=out)
# 定义函数 ljust,用于将数组 `a` 中的元素左对齐,填充至长度为 `width` 的字符串中
def ljust(a, width, fillchar=' '):
    """
    Return an array with the elements of `a` left-justified in a
    string of length `width`.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入数组,可以是字符串数组或字节串数组

    width : array_like, with any integer dtype
        结果字符串的长度,除非 `width < str_len(a)`。

    fillchar : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        可选参数,用于填充的字符(默认为空格)。

    Returns
    -------
    out : ndarray
        返回一个数组,包含了左对齐后的字符串,其数据类型为 `StringDType`、`bytes_` 或 `str_`,取决于输入类型。

    See Also
    --------
    str.ljust

    Notes
    -----
    虽然 `a` 和 `fillchar` 可能具有不同的数据类型,
    但在 `a` 的数据类型为 "S" 时,如果 `fillchar` 中包含非 ASCII 字符,
    则会引发 `ValueError` 异常。

    Examples
    --------
    >>> c = np.array(['aAaAaA', '  aA  ', 'abBABba'])
    >>> np.strings.ljust(c, width=3)
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')
    >>> np.strings.ljust(c, width=9)
    array(['aAaAaA   ', '  aA     ', 'abBABba  '], dtype='<U9')

    """
    # 将 `a` 转换为任意数组
    a = np.asanyarray(a)
    # 将 `fillchar` 转换为与 `a` 相同的数据类型的数组
    fillchar = np.asanyarray(fillchar, dtype=a.dtype)

    # 如果 `fillchar` 中有长度不为 1 的元素,则引发 TypeError 异常
    if np.any(str_len(fillchar) != 1):
        raise TypeError(
            "The fill character must be exactly one character long")

    # 如果 `a` 的数据类型为 "T",则调用 `_ljust` 函数来执行左对齐操作
    if a.dtype.char == "T":
        return _ljust(a, width, fillchar)

    # 计算字符串数组 `a` 中每个字符串的最大长度与 `width` 的最大值作为新的 `width`
    width = np.maximum(str_len(a), width)
    # 计算输出数组的形状,以适应 `a`、`width` 和 `fillchar`
    shape = np.broadcast_shapes(a.shape, width.shape, fillchar.shape)
    # 根据结果数据类型创建一个新的输出数组
    out_dtype = f"{a.dtype.char}{width.max()}"
    out = np.empty_like(a, shape=shape, dtype=out_dtype)
    # 调用 `_ljust` 函数执行左对齐操作,并将结果存储在 `out` 中
    return _ljust(a, width, fillchar, out=out)



# 定义函数 rjust,用于将数组 `a` 中的元素右对齐,填充至长度为 `width` 的字符串中
def rjust(a, width, fillchar=' '):
    """
    Return an array with the elements of `a` right-justified in a
    string of length `width`.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入数组,可以是字符串数组或字节串数组

    width : array_like, with any integer dtype
        结果字符串的长度,除非 `width < str_len(a)`。

    fillchar : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        可选参数,用于填充的字符(默认为空格)。

    Returns
    -------
    out : ndarray
        返回一个数组,包含了右对齐后的字符串,其数据类型为 `StringDType`、`bytes_` 或 `str_`,取决于输入类型。

    See Also
    --------
    str.rjust

    Notes
    -----
    虽然 `a` 和 `fillchar` 可能具有不同的数据类型,
    但在 `a` 的数据类型为 "S" 时,如果 `fillchar` 中包含非 ASCII 字符,
    则会引发 `ValueError` 异常。

    Examples
    --------
    >>> a = np.array(['aAaAaA', '  aA  ', 'abBABba'])
    >>> np.strings.rjust(a, width=3)
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')
    >>> np.strings.rjust(a, width=9)
    array(['   aAaAaA', '     aA  ', '  abBABba'], dtype='<U9')

    """
    # 将 `a` 转换为任意数组
    a = np.asanyarray(a)
    # 将 fillchar 转换为与数组 a 相同的数据类型的 NumPy 数组
    fillchar = np.asanyarray(fillchar, dtype=a.dtype)

    # 如果 fillchar 中有任何一个元素的长度不等于 1,则抛出 TypeError 异常
    if np.any(str_len(fillchar) != 1):
        raise TypeError(
            "The fill character must be exactly one character long")

    # 如果数组 a 的数据类型是 'T'(字符串类型),则调用 _rjust 函数右对齐数组 a
    if a.dtype.char == "T":
        return _rjust(a, width, fillchar)

    # 计算数组 a 和 width 的最大字符串长度
    width = np.maximum(str_len(a), width)

    # 计算广播后的形状,以适应 a 的形状、width 的形状和 fillchar 的形状
    shape = np.broadcast_shapes(a.shape, width.shape, fillchar.shape)

    # 根据计算得到的形状和数据类型创建一个与 a 相同类型的空数组 out
    out_dtype = f"{a.dtype.char}{width.max()}"
    out = np.empty_like(a, shape=shape, dtype=out_dtype)

    # 调用 _rjust 函数,使用计算得到的数组 a、width 和 fillchar 进行右对齐操作,结果存入 out
    return _rjust(a, width, fillchar, out=out)
# 定义一个函数 zfill,用于将数字字符串左侧填充零。如果有符号前缀(+/-),则在符号字符之后填充零。
def zfill(a, width):
    """
    Return the numeric string left-filled with zeros. A leading
    sign prefix (``+``/``-``) is handled by inserting the padding
    after the sign character rather than before.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入参数 `a`,可以是数组形式,数据类型可以是字符串、字节串或字符串数组
    width : array_like, with any integer dtype
        输入参数 `width`,可以是任意整数数据类型的数组,指定要填充到的字符串宽度

    Returns
    -------
    out : ndarray
        返回值是一个数组,数据类型为 `StringDType`、`bytes_` 或 `str_`,具体取决于输入类型

    See Also
    --------
    str.zfill

    Examples
    --------
    >>> np.strings.zfill(['1', '-1', '+1'], 3)
    array(['001', '-01', '+01'], dtype='<U3')

    """
    # 将输入参数 `a` 转换为任意数组
    a = np.asanyarray(a)

    # 如果输入数组 `a` 的数据类型字符为 "T",则调用内部函数 `_zfill` 处理
    if a.dtype.char == "T":
        return _zfill(a, width)

    # 计算 `a` 中每个元素的字符串长度,并与 `width` 取最大值
    width = np.maximum(str_len(a), width)
    # 广播 `a` 和 `width` 的形状,得到输出数组的形状
    shape = np.broadcast_shapes(a.shape, width.shape)
    # 输出数组的数据类型,由 `a` 的数据类型字符和 `width` 最大值组成
    out_dtype = f"{a.dtype.char}{width.max()}"
    # 创建一个和 `a` 类型相同、形状为 `shape`、数据类型为 `out_dtype` 的空数组
    out = np.empty_like(a, shape=shape, dtype=out_dtype)
    # 调用内部函数 `_zfill` 处理并返回结果
    return _zfill(a, width, out=out)


# 定义一个函数 lstrip,用于去除每个元素开头的指定字符集合
def lstrip(a, chars=None):
    """
    For each element in `a`, return a copy with the leading characters
    removed.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入参数 `a`,可以是数组形式,数据类型可以是字符串、字节串或字符串数组
    chars : scalar with the same dtype as ``a``, optional
       The ``chars`` argument is a string specifying the set of
       characters to be removed. If ``None``, the ``chars``
       argument defaults to removing whitespace. The ``chars`` argument
       is not a prefix or suffix; rather, all combinations of its
       values are stripped.

    Returns
    -------
    out : ndarray
        返回值是一个数组,数据类型为 `StringDType`、`bytes_` 或 `str_`,具体取决于输入类型

    See Also
    --------
    str.lstrip

    Examples
    --------
    >>> c = np.array(['aAaAaA', '  aA  ', 'abBABba'])
    >>> c
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')
    # The 'a' variable is unstripped from c[1] because of leading whitespace.
    >>> np.strings.lstrip(c, 'a')
    array(['AaAaA', '  aA  ', 'bBABba'], dtype='<U7')
    >>> np.strings.lstrip(c, 'A') # leaves c unchanged
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')
    >>> (np.strings.lstrip(c, ' ') == np.strings.lstrip(c, '')).all()
    np.False_
    >>> (np.strings.lstrip(c, ' ') == np.strings.lstrip(c)).all()
    np.True_

    """
    # 如果 `chars` 参数为 `None`,则调用内部函数 `_lstrip_whitespace` 去除空白字符
    if chars is None:
        return _lstrip_whitespace(a)
    # 否则调用内部函数 `_lstrip_chars` 去除指定的字符集合 `chars`
    return _lstrip_chars(a, chars)


# 定义一个函数 rstrip,用于去除每个元素末尾的指定字符集合
def rstrip(a, chars=None):
    """
    For each element in `a`, return a copy with the trailing characters
    removed.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入参数 `a`,可以是数组形式,数据类型可以是字符串、字节串或字符串数组
    chars : scalar with the same dtype as ``a``, optional
       The ``chars`` argument is a string specifying the set of
       characters to be removed. If ``None``, the ``chars``
       argument defaults to removing whitespace. The ``chars`` argument
       is not a prefix or suffix; rather, all combinations of its
       values are stripped.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.rstrip

    Examples
    --------
    >>> c = np.array(['aAaAaA', 'abBABba'])
    >>> c
    array(['aAaAaA', 'abBABba'], dtype='<U7')
    >>> np.strings.rstrip(c, 'a')
    array(['aAaAaA', 'abBABb'], dtype='<U7')
    >>> np.strings.rstrip(c, 'A')
    array(['aAaAa', 'abBABba'], dtype='<U7')

    """
    # 如果 chars 参数为 None,则调用 _rstrip_whitespace 函数去除字符串末尾的空白字符
    if chars is None:
        return _rstrip_whitespace(a)
    # 否则,调用 _rstrip_chars 函数去除字符串末尾指定的字符集合
    return _rstrip_chars(a, chars)
def strip(a, chars=None):
    """
    For each element in `a`, return a copy with the leading and
    trailing characters removed.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array.
    chars : scalar with the same dtype as ``a``, optional
        The ``chars`` argument is a string specifying the set of
        characters to be removed. If ``None``, the ``chars``
        argument defaults to removing whitespace. The ``chars`` argument
        is not a prefix or suffix; rather, all combinations of its
        values are stripped.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.strip

    Examples
    --------
    >>> c = np.array(['aAaAaA', '  aA  ', 'abBABba'])
    >>> c
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')
    >>> np.strings.strip(c)
    array(['aAaAaA', 'aA', 'abBABba'], dtype='<U7')
    # 'a' unstripped from c[1] because of leading whitespace.
    >>> np.strings.strip(c, 'a')
    array(['AaAaA', '  aA  ', 'bBABb'], dtype='<U7')
    # 'A' unstripped from c[1] because of trailing whitespace.
    >>> np.strings.strip(c, 'A')
    array(['aAaAa', '  aA  ', 'abBABba'], dtype='<U7')

    """
    # 如果 `chars` 参数为 None,则调用 _strip_whitespace 函数去除空白字符
    if chars is None:
        return _strip_whitespace(a)
    # 否则,调用 _strip_chars 函数去除指定的字符集合
    return _strip_chars(a, chars)


def upper(a):
    """
    Return an array with the elements converted to uppercase.

    Calls :meth:`str.upper` element-wise.

    For 8-bit strings, this method is locale-dependent.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.upper

    Examples
    --------
    >>> c = np.array(['a1b c', '1bca', 'bca1']); c
    array(['a1b c', '1bca', 'bca1'], dtype='<U5')
    >>> np.strings.upper(c)
    array(['A1B C', '1BCA', 'BCA1'], dtype='<U5')

    """
    # 将输入数组 `a` 转换为 ndarray 类型
    a_arr = np.asarray(a)
    # 调用 _vec_string 函数,将元素逐个转换为大写形式
    return _vec_string(a_arr, a_arr.dtype, 'upper')


def lower(a):
    """
    Return an array with the elements converted to lowercase.

    Call :meth:`str.lower` element-wise.

    For 8-bit strings, this method is locale-dependent.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.lower

    Examples
    --------
    >>> c = np.array(['A1B C', '1BCA', 'BCA1']); c
    array(['A1B C', '1BCA', 'BCA1'], dtype='<U5')
    >>> np.strings.lower(c)
    array(['a1b c', '1bca', 'bca1'], dtype='<U5')

    """
    # 将输入数组 `a` 转换为 ndarray 类型
    a_arr = np.asarray(a)
    # 调用 _vec_string 函数,将元素逐个转换为小写形式
    return _vec_string(a_arr, a_arr.dtype, 'lower')


def swapcase(a):
    """
    Return an array with uppercase characters converted to lowercase
    and vice versa.

    Call :meth:`str.swapcase` element-wise.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.swapcase

    Examples
    --------
    >>> c = np.array(['aAaAaA', '  aA  ', 'abBABba']); c
    array(['aAaAaA', '  aA  ', 'abBABba'], dtype='<U7')
    >>> np.strings.swapcase(c)
    array(['AaAaAa', '  Aa  ', 'ABbabBA'], dtype='<U7')

    """
    # 将输入数组 `a` 转换为 ndarray 类型
    a_arr = np.asarray(a)
    # 调用 _vec_string 函数,将大写转换为小写,小写转换为大写
    return _vec_string(a_arr, a_arr.dtype, 'swapcase')
    """
    将字符串中的大写字符转换为小写字符,小写字符转换为大写字符,并返回副本。
    
    调用 :meth:`str.swapcase` 来实现逐元素转换。
    
    对于8位字符串,此方法依赖于本地化设置。
    
    Parameters
    ----------
    a : array-like,具有 ``StringDType``, ``bytes_``, 或 ``str_`` 数据类型
        输入数组。
    
    Returns
    -------
    out : ndarray
        输出数组,数据类型为 ``StringDType``, ``bytes_`` 或 ``str_``,取决于输入类型。
    
    See Also
    --------
    str.swapcase
    
    Examples
    --------
    >>> c=np.array(['a1B c','1b Ca','b Ca1','cA1b'],'S5'); c
    array(['a1B c', '1b Ca', 'b Ca1', 'cA1b'],
        dtype='|S5')
    >>> np.strings.swapcase(c)
    array(['A1b C', '1B cA', 'B cA1', 'Ca1B'],
        dtype='|S5')
    
    """
    # 将输入的数组转换为 numpy 数组
    a_arr = np.asarray(a)
    # 调用内部函数 _vec_string,传入输入数组、数组的数据类型和操作类型 'swapcase',返回处理后的数组
    return _vec_string(a_arr, a_arr.dtype, 'swapcase')
def capitalize(a):
    """
    Return a copy of ``a`` with only the first character of each element
    capitalized.

    Calls :meth:`str.capitalize` element-wise.

    For byte strings, this method is locale-dependent.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array of strings to capitalize.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.capitalize

    Examples
    --------
    >>> c = np.array(['a1b2','1b2a','b2a1','2a1b'],'S4'); c
    array(['a1b2', '1b2a', 'b2a1', '2a1b'],
        dtype='|S4')
    >>> np.strings.capitalize(c)
    array(['A1b2', '1b2a', 'B2a1', '2a1b'],
        dtype='|S4')

    """
    # 将输入数组转换为 NumPy 数组
    a_arr = np.asarray(a)
    # 调用内部函数 _vec_string 进行字符串首字母大写处理
    return _vec_string(a_arr, a_arr.dtype, 'capitalize')


def title(a):
    """
    Return element-wise title cased version of string or unicode.

    Title case words start with uppercase characters, all remaining cased
    characters are lowercase.

    Calls :meth:`str.title` element-wise.

    For 8-bit strings, this method is locale-dependent.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.title

    Examples
    --------
    >>> c=np.array(['a1b c','1b ca','b ca1','ca1b'],'S5'); c
    array(['a1b c', '1b ca', 'b ca1', 'ca1b'],
        dtype='|S5')
    >>> np.strings.title(c)
    array(['A1B C', '1B Ca', 'B Ca1', 'Ca1B'],
        dtype='|S5')

    """
    # 将输入数组转换为 NumPy 数组
    a_arr = np.asarray(a)
    # 调用内部函数 _vec_string 进行字符串标题格式处理
    return _vec_string(a_arr, a_arr.dtype, 'title')


def replace(a, old, new, count=-1):
    """
    For each element in ``a``, return a copy of the string with
    occurrences of substring ``old`` replaced by ``new``.

    Parameters
    ----------
    a : array_like, with ``bytes_`` or ``str_`` dtype

    old, new : array_like, with ``bytes_`` or ``str_`` dtype

    count : array_like, with ``int_`` dtype
        If the optional argument ``count`` is given, only the first
        ``count`` occurrences are replaced.

    Returns
    -------
    out : ndarray
        Output array of ``StringDType``, ``bytes_`` or ``str_`` dtype,
        depending on input types

    See Also
    --------
    str.replace
    
    Examples
    --------
    >>> a = np.array(["That is a mango", "Monkeys eat mangos"])
    >>> np.strings.replace(a, 'mango', 'banana')
    array(['That is a banana', 'Monkeys eat bananas'], dtype='<U19')

    >>> a = np.array(["The dish is fresh", "This is it"])
    >>> np.strings.replace(a, 'is', 'was')
    array(['The dwash was fresh', 'Thwas was it'], dtype='<U19')
    
    """
    # 将输入数组转换为 NumPy 通用数组
    arr = np.asanyarray(a)
    # 获取数组的数据类型
    a_dt = arr.dtype
    # 将旧数组转换为NumPy数组,如果没有指定dtype,则使用a_dt
    old = np.asanyarray(old, dtype=getattr(old, 'dtype', a_dt))
    
    # 将新数组转换为NumPy数组,如果没有指定dtype,则使用a_dt
    new = np.asanyarray(new, dtype=getattr(new, 'dtype', a_dt))
    
    # 将count转换为NumPy数组
    count = np.asanyarray(count)
    
    # 如果数组arr的dtype的字符代码为"T"(代表'timedelta'类型),则调用_replace函数进行替换操作并返回结果
    if arr.dtype.char == "T":
        return _replace(arr, old, new, count)
    
    # 获取np.int64类型的最大值
    max_int64 = np.iinfo(np.int64).max
    
    # 调用_count_ufunc函数计算在数组arr中与old匹配的元素数量,限制计数不超过max_int64
    counts = _count_ufunc(arr, old, 0, max_int64)
    
    # 根据count数组的值对counts数组进行调整:如果count小于0,则保留原有counts值;否则取counts和count中较小的值
    counts = np.where(count < 0, counts, np.minimum(counts, count))
    
    # 根据替换操作计算输出数组的缓冲区大小,buffersizes的每个元素表示对应位置的替换后字符串的长度变化
    buffersizes = str_len(arr) + counts * (str_len(new) - str_len(old))
    
    # 构建输出数组的dtype,字符代码为原始arr的dtype的字符代码,并根据buffersizes的最大值确定dtype的长度
    out_dtype = f"{arr.dtype.char}{buffersizes.max()}"
    
    # 根据out_dtype创建一个与arr形状相同且dtype为out_dtype的空数组out
    out = np.empty_like(arr, shape=buffersizes.shape, dtype=out_dtype)
    
    # 调用_replace函数,使用old、new和counts替换arr中的元素,并将结果存入out数组中
    return _replace(arr, old, new, counts, out=out)
# 返回一个字符串,该字符串是序列 `seq` 中字符串连接而成的结果。
# 对每个元素调用 :meth:`str.join` 方法进行连接。
def _join(sep, seq):
    # 调用 _vec_string 函数,将 sep 和 seq 转换为字节或字符串数组,然后进行连接操作
    return _to_bytes_or_str_array(
        _vec_string(sep, np.object_, 'join', (seq,)), seq)


# 对于每个元素 `a`,使用 `sep` 作为分隔符字符串,返回字符串中的单词列表。
# 对每个元素调用 :meth:`str.split` 方法进行分割。
def _split(a, sep=None, maxsplit=None):
    # 这将返回一个大小不同的列表数组,因此我们将其保留为对象数组
    return _vec_string(
        a, np.object_, 'split', [sep] + _clean_args(maxsplit))


# 对于每个元素 `a`,使用 `sep` 作为分隔符字符串,从右向左返回字符串中的单词列表。
# 对每个元素调用 :meth:`str.rsplit` 方法进行分割。
# 与 `split` 类似,不同之处在于从右侧开始分割。
def _rsplit(a, sep=None, maxsplit=None):
    return _vec_string(
        a, np.object_, 'rsplit', [sep] + _clean_args(maxsplit))


这些函数是针对 NumPy 数组中包含的字符串元素进行操作的工具函数,使用了 NumPy 的字符串处理功能。
    """
    # 返回一个数组,其中包含不同大小的列表,因此我们将其保留为对象数组
    # 这个数组可能包含不同长度的列表,因此数据类型被指定为对象数组
    return _vec_string(
        a, np.object_, 'rsplit', [sep] + _clean_args(maxsplit))
    """
def _splitlines(a, keepends=None):
    """
    对 `a` 中的每个元素进行操作,返回每个元素按行划分后的列表。

    调用 :meth:`str.splitlines` 方法逐个元素处理。

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入数组,元素类型为字符串或字节流
    keepends : bool, optional
        如果为 True,则结果列表中保留行结束符;默认情况下不包含行结束符。

    Returns
    -------
    out : ndarray
        包含列表对象的数组

    See Also
    --------
    str.splitlines

    """
    # 调用 `_vec_string` 函数对每个元素进行 `splitlines` 操作,传递 `keepends` 参数
    return _vec_string(
        a, np.object_, 'splitlines', _clean_args(keepends))


def partition(a, sep):
    """
    对 `a` 中的每个元素围绕 `sep` 进行分区。

    对 `a` 中的每个元素,在第一次出现 `sep` 的位置进行分割,并返回一个三元组,
    包含分隔符之前的部分、分隔符本身和分隔符之后的部分。如果找不到分隔符,
    则三元组的第一项将包含整个字符串,第二和第三项将为空字符串。

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        输入数组
    sep : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        用于分割每个字符串元素的分隔符。

    Returns
    -------
    out : 3-tuple:
        - 元素类型为 ``StringDType``, ``bytes_`` 或 ``str_`` 的数组,包含分隔符之前的部分
        - 元素类型为 ``StringDType``, ``bytes_`` 或 ``str_`` 的数组,包含分隔符本身
        - 元素类型为 ``StringDType``, ``bytes_`` 或 ``str_`` 的数组,包含分隔符之后的部分

    See Also
    --------
    str.partition

    Examples
    --------
    >>> x = np.array(["Numpy is nice!"])
    >>> np.strings.partition(x, " ")
    (array(['Numpy'], dtype='<U5'),
     array([' '], dtype='<U1'),
     array(['is nice!'], dtype='<U8'))

    """
    # 将 `a` 转换为 `ndarray`
    a = np.asanyarray(a)
    # 当问题围绕视图问题解决时,切换到 copy=False
    sep = np.array(sep, dtype=a.dtype, copy=True, subok=True)
    if a.dtype.char == "T":
        return _partition(a, sep)

    # 在 `a` 中寻找 `sep` 的位置
    pos = _find_ufunc(a, sep, 0, MAX)
    a_len = str_len(a)
    sep_len = str_len(sep)

    not_found = pos < 0
    buffersizes1 = np.where(not_found, a_len, pos)
    buffersizes3 = np.where(not_found, 0, a_len - pos - sep_len)

    # 计算输出的 dtype
    out_dtype = ",".join([f"{a.dtype.char}{n}" for n in (
        buffersizes1.max(),
        1 if np.all(not_found) else sep_len.max(),
        buffersizes3.max(),
    )])
    shape = np.broadcast_shapes(a.shape, sep.shape)
    # 创建输出数组
    out = np.empty_like(a, shape=shape, dtype=out_dtype)
    return _partition_index(a, sep, pos, out=(out["f0"], out["f1"], out["f2"]))
    occurrence of ``sep``, and return a 3-tuple containing the part
    before the separator, the separator itself, and the part after
    the separator. If the separator is not found, the third item of
    the tuple will contain the whole string, and the first and second
    ones will be the empty string.

    Parameters
    ----------
    a : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Input array
    sep : array-like, with ``StringDType``, ``bytes_``, or ``str_`` dtype
        Separator to split each string element in ``a``.

    Returns
    -------
    out : 3-tuple:
        - array with ``StringDType``, ``bytes_`` or ``str_`` dtype with the
          part before the separator
        - array with ``StringDType``, ``bytes_`` or ``str_`` dtype with the
          separator
        - array with ``StringDType``, ``bytes_`` or ``str_`` dtype with the
          part after the separator

    See Also
    --------
    str.rpartition

    Examples
    --------
    >>> a = np.array(['aAaAaA', '  aA  ', 'abBABba'])
    >>> np.strings.rpartition(a, 'A')
    (array(['aAaAa', '  a', 'abB'], dtype='<U5'),
     array(['A', 'A', 'A'], dtype='<U1'),
     array(['', '  ', 'Bba'], dtype='<U3'))

    """
    # 将输入的数组 a 转换为 NumPy 数组
    a = np.asanyarray(a)
    # TODO switch to copy=False when issues around views are fixed
    # 将分隔符数组 sep 转换为与 a 相同类型的 NumPy 数组副本
    sep = np.array(sep, dtype=a.dtype, copy=True, subok=True)
    # 如果 a 的数据类型是 'T',调用 _rpartition 函数处理
    if a.dtype.char == "T":
        return _rpartition(a, sep)

    # 使用 _rfind_ufunc 函数查找 sep 在 a 中最后出现的位置
    pos = _rfind_ufunc(a, sep, 0, MAX)
    # 计算 a 和 sep 的长度
    a_len = str_len(a)
    sep_len = str_len(sep)

    # 判断是否找到分隔符,如果没找到则设置相应的缓冲区大小为 0 或者 a 和 sep 的长度
    not_found = pos < 0
    buffersizes1 = np.where(not_found, 0, pos)
    buffersizes3 = np.where(not_found, a_len, a_len - pos - sep_len)

    # 构建输出的数据类型,包括部分之前的长度、分隔符长度和部分之后的长度
    out_dtype = ",".join([f"{a.dtype.char}{n}" for n in (
        buffersizes1.max(),
        1 if np.all(not_found) else sep_len.max(),
        buffersizes3.max(),
    )])
    # 广播输入数组 a 和 sep 的形状
    shape = np.broadcast_shapes(a.shape, sep.shape)
    # 创建一个与 a 类型相同的空数组作为输出
    out = np.empty_like(a, shape=shape, dtype=out_dtype)
    # 调用 _rpartition_index 函数进行分区操作,将结果存储在 out 中的对应字段
    return _rpartition_index(
        a, sep, pos, out=(out["f0"], out["f1"], out["f2"]))
def translate(a, table, deletechars=None):
    """
    对于 `a` 中的每个元素,返回一个新字符串副本,其中删除了在可选参数 `deletechars` 中出现的所有字符,并将剩余字符通过给定的转换表映射。

    逐元素调用 :meth:`str.translate`。

    Parameters
    ----------
    a : array-like, with `np.bytes_` or `np.str_` dtype
        输入数组,元素类型为 `np.bytes_` 或 `np.str_`

    table : str of length 256
        长度为 256 的字符串转换表

    deletechars : str, optional
        要删除的字符集合,可选参数

    Returns
    -------
    out : ndarray
        输出的字符串数组,根据输入类型为 str 或 unicode

    See Also
    --------
    str.translate

    Examples
    --------
    >>> a = np.array(['a1b c', '1bca', 'bca1'])
    >>> table = a[0].maketrans('abc', '123')
    >>> deletechars = ' '
    >>> np.char.translate(a, table, deletechars)
    array(['112 3', '1231', '2311'], dtype='<U5')
    """
    # 将输入 `a` 转换为 ndarray 类型
    a_arr = np.asarray(a)
    # 如果 `a_arr` 的元素类型是字符串类型
    if issubclass(a_arr.dtype.type, np.str_):
        # 调用 _vec_string 函数处理字符串类型的数组 `a_arr`,并返回结果
        return _vec_string(
            a_arr, a_arr.dtype, 'translate', (table,))
    else:
        # 否则,调用 _vec_string 函数处理非字符串类型的数组 `a_arr`,并返回结果
        return _vec_string(
            a_arr,
            a_arr.dtype,
            'translate',
            [table] + _clean_args(deletechars)
        )

.\numpy\numpy\_core\strings.pyi

# 引入类型提示所需的模块和类型定义
from typing import Any, overload

# 引入 NumPy 模块
import numpy as np
# 引入 NumPy 的部分类型定义
from numpy._typing import (
    NDArray,
    _ArrayLikeStr_co as U_co,
    _ArrayLikeBytes_co as S_co,
    _ArrayLikeInt_co as i_co,
    _ArrayLikeBool_co as b_co,
)

# equal 函数的重载定义,比较两个数组或字符串是否相等,返回布尔数组
@overload
def equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ...
@overload
def equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ...

# not_equal 函数的重载定义,比较两个数组或字符串是否不相等,返回布尔数组
@overload
def not_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ...
@overload
def not_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ...

# greater_equal 函数的重载定义,比较两个数组或字符串是否大于或等于,返回布尔数组
@overload
def greater_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ...
@overload
def greater_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ...

# less_equal 函数的重载定义,比较两个数组或字符串是否小于或等于,返回布尔数组
@overload
def less_equal(x1: U_co, x2: U_co) -> NDArray[np.bool]: ...
@overload
def less_equal(x1: S_co, x2: S_co) -> NDArray[np.bool]: ...

# greater 函数的重载定义,比较两个数组或字符串是否大于,返回布尔数组
@overload
def greater(x1: U_co, x2: U_co) -> NDArray[np.bool]: ...
@overload
def greater(x1: S_co, x2: S_co) -> NDArray[np.bool]: ...

# less 函数的重载定义,比较两个数组或字符串是否小于,返回布尔数组
@overload
def less(x1: U_co, x2: U_co) -> NDArray[np.bool]: ...
@overload
def less(x1: S_co, x2: S_co) -> NDArray[np.bool]: ...

# add 函数的重载定义,对两个数组或字符串进行加法操作,返回新的数组或字符串
@overload
def add(x1: U_co, x2: U_co) -> NDArray[np.str_]: ...
@overload
def add(x1: S_co, x2: S_co) -> NDArray[np.bytes_]: ...

# multiply 函数的重载定义,对数组或字符串进行乘法操作,返回新的数组或字符串
@overload
def multiply(a: U_co, i: i_co) -> NDArray[np.str_]: ...
@overload
def multiply(a: S_co, i: i_co) -> NDArray[np.bytes_]: ...

# mod 函数的重载定义,对数组或字符串进行取模操作,返回新的数组或字符串
@overload
def mod(a: U_co, value: Any) -> NDArray[np.str_]: ...
@overload
def mod(a: S_co, value: Any) -> NDArray[np.bytes_]: ...

# isalpha 函数的定义,判断数组或字符串中的元素是否都为字母,返回布尔数组
def isalpha(x: U_co | S_co) -> NDArray[np.bool]: ...

# isalnum 函数的定义,判断数组或字符串中的元素是否都为字母或数字,返回布尔数组
def isalnum(a: U_co | S_co) -> NDArray[np.bool]: ...

# isdigit 函数的定义,判断数组或字符串中的元素是否都为数字,返回布尔数组
def isdigit(x: U_co | S_co) -> NDArray[np.bool]: ...

# isspace 函数的定义,判断数组或字符串中的元素是否都为空格,返回布尔数组
def isspace(x: U_co | S_co) -> NDArray[np.bool]: ...

# isdecimal 函数的定义,判断数组或字符串中的元素是否都为十进制数字,返回布尔数组
def isdecimal(x: U_co) -> NDArray[np.bool]: ...

# isnumeric 函数的定义,判断数组或字符串中的元素是否都为数字,包括数字字符、Unicode数字,返回布尔数组
def isnumeric(x: U_co) -> NDArray[np.bool]: ...

# islower 函数的定义,判断数组或字符串中的元素是否都为小写字母,返回布尔数组
def islower(a: U_co | S_co) -> NDArray[np.bool]: ...

# istitle 函数的定义,判断数组或字符串中的元素是否符合标题格式,返回布尔数组
def istitle(a: U_co | S_co) -> NDArray[np.bool]: ...

# isupper 函数的定义,判断数组或字符串中的元素是否都为大写字母,返回布尔数组
def isupper(a: U_co | S_co) -> NDArray[np.bool]: ...

# str_len 函数的定义,返回数组或字符串中每个元素的长度,作为整数数组
def str_len(x: U_co | S_co) -> NDArray[np.int_]: ...

# find 函数的重载定义,查找子字符串在数组或字符串中的位置,返回整数数组
@overload
def find(
    a: U_co,
    sub: U_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.int_]: ...
@overload
def find(
    a: S_co,
    sub: S_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.int_]: ...

# rfind 函数的重载定义,从右侧开始查找子字符串在数组或字符串中的位置,返回整数数组
@overload
def rfind(
    a: U_co,
    sub: U_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.int_]: ...
@overload
def rfind(
    a: S_co,
    sub: S_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.int_]: ...

# index 函数的重载定义,查找子字符串在数组或字符串中的位置,返回整数数组
@overload
def index(
    a: U_co,
    sub: U_co,
    start: i_co = ...,
    end: None | i_co = ...,
) -> NDArray[np.int_]: ...
@overload
def index(
    a: S_co,
    sub: S_co,
    start: i_co = ...,
    end: None | i_co = ...,
) -> NDArray[np.int_]: ...

# rindex 函数的重载定义,从右侧开始查找子字符串在数组或字符串中的位置,返回整数数组
@overload
def rindex(
    a: U_co,
    sub: U_co,
    start: i_co = ...,
    end: None | i_co = ...,
) -> NDArray[np.int_]: ...
@overload
def rindex(
    a: S_co,
    sub: S_co,
    start: i_co = ...,
    end: None | i_co = ...,
) -> NDArray[np.int_]: ...

# count 函数的重载定义,统计子字符串在数组或字符串中出现的次数,返回整数数组
@overload
def count(
    a: U_co,
    # a 是变量名,表示一个类型为 U_co 的变量
    sub: U_co,
    # sub 是变量名,表示一个类型为 U_co 的变量
    start: i_co = ...,
    # start 是变量名,表示一个类型为 i_co 的变量,并且初始化为 ...
    end: i_co | None = ...,
    # end 是变量名,表示一个类型为 i_co 或者 None 的变量,并且初始化为 ...
# 函数签名,指定返回类型为 numpy 中的整数数组
) -> NDArray[np.int_]: ...

# 函数签名,计算字符串或字节串中子串出现的次数
@overload
def count(
    a: S_co,
    sub: S_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.int_]: ...

# 函数签名,检查字符串或字节串是否以指定前缀开头,返回布尔值数组
@overload
def startswith(
    a: U_co,
    prefix: U_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.bool]: ...

# 函数签名,检查字符串或字节串是否以指定后缀结尾,返回布尔值数组
@overload
def endswith(
    a: U_co,
    suffix: U_co,
    start: i_co = ...,
    end: i_co | None = ...,
) -> NDArray[np.bool]: ...

# 函数签名,根据指定编码对字符串或字节串解码,返回字符串数组
def decode(
    a: S_co,
    encoding: None | str = ...,
    errors: None | str = ...,
) -> NDArray[np.str_]: ...

# 函数签名,根据指定编码对字符串或字节串编码,返回字节串数组
def encode(
    a: U_co,
    encoding: None | str = ...,
    errors: None | str = ...,
) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串中的制表符扩展为空格,返回字符串数组
@overload
def expandtabs(a: U_co, tabsize: i_co = ...) -> NDArray[np.str_]: ...
@overload
def expandtabs(a: S_co, tabsize: i_co = ...) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串居中对齐,返回字符串数组
@overload
def center(a: U_co, width: i_co, fillchar: U_co = ...) -> NDArray[np.str_]: ...
@overload
def center(a: S_co, width: i_co, fillchar: S_co = ...) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串左对齐,返回字符串数组
@overload
def ljust(a: U_co, width: i_co, fillchar: U_co = ...) -> NDArray[np.str_]: ...
@overload
def ljust(a: S_co, width: i_co, fillchar: S_co = ...) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串右对齐,返回字符串数组
@overload
def rjust(
    a: U_co,
    width: i_co,
    fillchar: U_co = ...,
) -> NDArray[np.str_]: ...
@overload
def rjust(
    a: S_co,
    width: i_co,
    fillchar: S_co = ...,
) -> NDArray[np.bytes_]: ...

# 函数签名,从字符串或字节串左侧移除空白字符,返回字符串数组
@overload
def lstrip(a: U_co, chars: None | U_co = ...) -> NDArray[np.str_]: ...
@overload
def lstrip(a: S_co, chars: None | S_co = ...) -> NDArray[np.bytes_]: ...

# 函数签名,从字符串或字节串右侧移除空白字符,返回字符串数组
@overload
def rstrip(a: U_co, char: None | U_co = ...) -> NDArray[np.str_]: ...
@overload
def rstrip(a: S_co, char: None | S_co = ...) -> NDArray[np.bytes_]: ...

# 函数签名,从字符串或字节串两侧移除空白字符,返回字符串数组
@overload
def strip(a: U_co, chars: None | U_co = ...) -> NDArray[np.str_]: ...
@overload
def strip(a: S_co, chars: None | S_co = ...) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串填充到指定长度,左侧用 '0' 填充,返回字符串数组
@overload
def zfill(a: U_co, width: i_co) -> NDArray[np.str_]: ...
@overload
def zfill(a: S_co, width: i_co) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串转换为大写,返回字符串数组
@overload
def upper(a: U_co) -> NDArray[np.str_]: ...
@overload
def upper(a: S_co) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串转换为小写,返回字符串数组
@overload
def lower(a: U_co) -> NDArray[np.str_]: ...
@overload
def lower(a: S_co) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串中的大小写互换,返回字符串数组
@overload
def swapcase(a: U_co) -> NDArray[np.str_]: ...
@overload
def swapcase(a: S_co) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串首字母大写,返回字符串数组
@overload
def capitalize(a: U_co) -> NDArray[np.str_]: ...
@overload
def capitalize(a: S_co) -> NDArray[np.bytes_]: ...

# 函数签名,将字符串或字节串的每个单词首字母大写,返回字符串数组
@overload
def title(a: U_co) -> NDArray[np.str_]: ...
@overload
def title(a: S_co) -> NDArray[np.bytes_]: ...

# 函数签名,替换字符串或字节串中的旧子串为新子串,可指定替换次数,返回字符串数组
def replace(
    a: U_co,
    old: U_co,
    new: U_co,
    count: i_co = ...,
) -> NDArray[np.str_]: ...
# 定义一个函数签名,声明将返回一个字节字符串数组,接受参数 a 作为不可变字符串、old 作为不可变字符串、new 作为不可变字符串,
# count 作为可选的整数,默认为省略号
def replace(
    a: S_co,
    old: S_co,
    new: S_co,
    count: i_co = ...,
) -> NDArray[np.bytes_]: ...

# 定义了一个函数签名的重载,接受一个分隔符 U_co 和一个序列 U_co,返回一个字符串数组
@overload
def join(sep: U_co, seq: U_co) -> NDArray[np.str_]: ...
# 定义了一个函数签名的重载,接受一个分隔符 S_co 和一个序列 S_co,返回一个字节字符串数组
@overload
def join(sep: S_co, seq: S_co) -> NDArray[np.bytes_]: ...

# 定义了一个函数签名的重载,接受一个字符串或对象 a、可选的分隔符 None 或对象 U_co,默认为省略号的最大分割数和整数类型的最大分割数,
# 返回一个对象数组
@overload
def split(
    a: U_co,
    sep: None | U_co = ...,
    maxsplit: None | i_co = ...,
) -> NDArray[np.object_]: ...
# 定义了一个函数签名的重载,接受一个字节字符串或对象 a、可选的分隔符 None 或字节字符串对象 S_co,默认为省略号的最大分割数和整数类型的最大分割数,
# 返回一个对象数组
@overload
def split(
    a: S_co,
    sep: None | S_co = ...,
    maxsplit: None | i_co = ...,
) -> NDArray[np.object_]: ...

# 定义了一个函数签名的重载,接受一个字符串或对象 a、可选的分隔符 None 或对象 U_co,默认为省略号的最大分割数和整数类型的最大分割数,
# 从右向左分割字符串,返回一个对象数组
@overload
def rsplit(
    a: U_co,
    sep: None | U_co = ...,
    maxsplit: None | i_co = ...,
) -> NDArray[np.object_]: ...
# 定义了一个函数签名的重载,接受一个字节字符串或对象 a、可选的分隔符 None 或字节字符串对象 S_co,默认为省略号的最大分割数和整数类型的最大分割数,
# 从右向左分割字节字符串,返回一个对象数组
@overload
def rsplit(
    a: S_co,
    sep: None | S_co = ...,
    maxsplit: None | i_co = ...,
) -> NDArray[np.object_]: ...

# 定义了一个函数签名的重载,接受一个字符串或对象 a、可选的保留结束符 keepends,默认为 None 或布尔值对象,返回一个对象数组
@overload
def splitlines(a: U_co, keepends: None | b_co = ...) -> NDArray[np.object_]: ...
# 定义了一个函数签名的重载,接受一个字节字符串或对象 a、可选的保留结束符 keepends,默认为 None 或布尔值对象,返回一个对象数组
@overload
def splitlines(a: S_co, keepends: None | b_co = ...) -> NDArray[np.object_]: ...

# 定义了一个函数签名的重载,接受一个字符串或对象 a、分隔符 sep,返回一个字符串数组
@overload
def partition(a: U_co, sep: U_co) -> NDArray[np.str_]: ...
# 定义了一个函数签名的重载,接受一个字节字符串或对象 a、分隔符 sep,返回一个字节字符串数组
@overload
def partition(a: S_co, sep: S_co) -> NDArray[np.bytes_]: ...

# 定义了一个函数签名的重载,接受一个字符串或对象 a、分隔符 sep,从右向左分隔字符串,返回一个字符串数组
@overload
def rpartition(a: U_co, sep: U_co) -> NDArray[np.str_]: ...
# 定义了一个函数签名的重载,接受一个字节字符串或对象 a、分隔符 sep,从右向左分隔字节字符串,返回一个字节字符串数组
@overload
def rpartition(a: S_co, sep: S_co) -> NDArray[np.bytes_]: ...

# 定义了一个函数签名的重载,接受一个字符串或对象 a、表格 table、可选的删除字符 deletechars,默认为 None 或对象 U_co,返回一个字符串数组
@overload
def translate(
    a: U_co,
    table: U_co,
    deletechars: None | U_co = ...,
) -> NDArray[np.str_]: ...
# 定义了一个函数签名的重载,接受一个字节字符串或对象 a、表格 table、可选的删除字符 deletechars,默认为 None 或字节字符串对象 S_co,返回一个字节字符串数组
@overload
def translate(
    a: S_co,
    table: S_co,
    deletechars: None | S_co = ...,
) -> NDArray[np.bytes_]: ...

.\numpy\numpy\_core\tests\data\generate_umath_validation_data.cpp

/*
 * 包含标准库头文件
 */
#include <algorithm>    // 提供算法操作
#include <fstream>      // 提供文件操作
#include <iostream>     // 提供标准输入输出流
#include <math.h>       // 提供数学函数
#include <random>       // 提供随机数生成器
#include <cstdio>       // 提供C风格输入输出
#include <ctime>        // 提供时间函数
#include <vector>       // 提供动态数组

/*
 * 定义结构体ufunc,用于存储数学函数信息
 */
struct ufunc {
    std::string name;                   // 函数名称
    double (*f32func)(double);          // 双精度浮点函数指针
    long double (*f64func)(long double);// 长双精度浮点函数指针
    float f32ulp;                       // 单精度浮点误差限
    float f64ulp;                       // 双精度浮点误差限
};

/*
 * 模板函数RandomFloat,生成指定范围[a, b)内的随机浮点数
 */
template <typename T>
T
RandomFloat(T a, T b)
{
    T random = ((T)rand()) / (T)RAND_MAX;   // 生成01之间的随机数
    T diff = b - a;                         // 计算范围差值
    T r = random * diff;                    // 缩放随机数到指定范围
    return a + r;                           // 返回随机数
}

/*
 * 模板函数append_random_array,向向量arr中添加N个指定范围[min, max)内的随机数
 */
template <typename T>
void
append_random_array(std::vector<T> &arr, T min, T max, size_t N)
{
    for (size_t ii = 0; ii < N; ++ii)
        arr.emplace_back(RandomFloat<T>(min, max));  // 调用RandomFloat生成随机数并添加到向量中
}

/*
 * 模板函数computeTrueVal,计算输入向量in中每个元素应用数学函数mathfunc后的结果,并返回结果向量
 */
template <typename T1, typename T2>
std::vector<T1>
computeTrueVal(const std::vector<T1> &in, T2 (*mathfunc)(T2))
{
    std::vector<T1> out;            // 定义输出向量
    for (T1 elem : in) {            // 遍历输入向量中的每个元素
        T2 elem_d = (T2)elem;       // 将元素转换为T2类型
        T1 out_elem = (T1)mathfunc(elem_d);    // 计算元素经过mathfunc函数后的结果
        out.emplace_back(out_elem); // 将结果添加到输出向量中
    }
    return out;                     // 返回结果向量
}

/*
 * FP range:
 * [-inf, -maxflt, -1., -minflt, -minden, 0., minden, minflt, 1., maxflt, inf]
 */

/*
 * 定义各种特殊浮点数常量的宏
 */
#define MINDEN std::numeric_limits<T>::denorm_min()      // 最小非规范化数
#define MINFLT std::numeric_limits<T>::min()             // 最小正浮点数
#define MAXFLT std::numeric_limits<T>::max()             // 最大浮点数
#define INF std::numeric_limits<T>::infinity()           // 正无穷大
#define qNAN std::numeric_limits<T>::quiet_NaN()         // 安静NaN
#define sNAN std::numeric_limits<T>::signaling_NaN()     // 信号NaN

/*
 * 模板函数generate_input_vector,根据函数名称func生成对应的输入向量
 */
template <typename T>
std::vector<T>
generate_input_vector(std::string func)
{
    std::vector<T> input = {MINDEN,  -MINDEN, MINFLT, -MINFLT, MAXFLT,
                            -MAXFLT, INF,     -INF,   qNAN,    sNAN,
                            -1.0,    1.0,     0.0,    -0.0};   // 初始化输入向量

    // 根据函数名称func生成不同范围的随机数并添加到输入向量中
    // [-1.0, 1.0]
    if ((func == "arcsin") || (func == "arccos") || (func == "arctanh")) {
        append_random_array<T>(input, -1.0, 1.0, 700);
    }
    // (0.0, INF]
    else if ((func == "log2") || (func == "log10")) {
        append_random_array<T>(input, 0.0, 1.0, 200);
        append_random_array<T>(input, MINDEN, MINFLT, 200);
        append_random_array<T>(input, MINFLT, 1.0, 200);
        append_random_array<T>(input, 1.0, MAXFLT, 200);
    }
    // (-1.0, INF]
    else if (func == "log1p") {
        append_random_array<T>(input, -1.0, 1.0, 200);
        append_random_array<T>(input, -MINFLT, -MINDEN, 100);
        append_random_array<T>(input, -1.0, -MINFLT, 100);
        append_random_array<T>(input, MINDEN, MINFLT, 100);
        append_random_array<T>(input, MINFLT, 1.0, 100);
        append_random_array<T>(input, 1.0, MAXFLT, 100);
    }
    // [1.0, INF]
    else if (func == "arccosh") {
        append_random_array<T>(input, 1.0, 2.0, 400);
        append_random_array<T>(input, 2.0, MAXFLT, 300);
    }
    // [-INF, INF]
    // 否则分支:在 input 后追加不同范围的随机数组成分
    append_random_array<T>(input, -1.0, 1.0, 100);
    append_random_array<T>(input, MINDEN, MINFLT, 100);
    append_random_array<T>(input, -MINFLT, -MINDEN, 100);
    append_random_array<T>(input, MINFLT, 1.0, 100);
    append_random_array<T>(input, -1.0, -MINFLT, 100);
    append_random_array<T>(input, 1.0, MAXFLT, 100);
    append_random_array<T>(input, -MAXFLT, -100.0, 100);

    // 对 input 中的元素进行随机重排
    std::random_shuffle(input.begin(), input.end());
    // 返回重排后的 input 数组
    return input;
}

.\numpy\numpy\_core\tests\examples\cython\checks.pyx

"""
Functions in this module give python-space wrappers for cython functions
exposed in numpy/__init__.pxd, so they can be tested in test_cython.py
"""
# 导入Cython声明
cimport numpy as cnp
# 导入numpy数组支持
cnp.import_array()

# 检查对象是否为timedelta64类型
def is_td64(obj):
    return cnp.is_timedelta64_object(obj)

# 检查对象是否为datetime64类型
def is_dt64(obj):
    return cnp.is_datetime64_object(obj)

# 获取datetime64对象的值
def get_dt64_value(obj):
    return cnp.get_datetime64_value(obj)

# 获取timedelta64对象的值
def get_td64_value(obj):
    return cnp.get_timedelta64_value(obj)

# 获取datetime64对象的单位
def get_dt64_unit(obj):
    return cnp.get_datetime64_unit(obj)

# 检查对象是否为整数(包括numpy.int和Python的int)
def is_integer(obj):
    return isinstance(obj, (cnp.integer, int))

# 获取ISO 8601日期时间字符串的长度
def get_datetime_iso_8601_strlen():
    return cnp.get_datetime_iso_8601_strlen(0, cnp.NPY_FR_ns)

# 将datetime64对象转换为datetimestruct结构
def convert_datetime64_to_datetimestruct():
    cdef:
        cnp.npy_datetimestruct dts  # datetimestruct结构体
        cnp.PyArray_DatetimeMetaData meta  # datetime元数据
        cnp.int64_t value = 1647374515260292  # 示例时间戳

    meta.base = cnp.NPY_FR_us  # 设置时间基准为微秒
    meta.num = 1  # 设置数量为1
    cnp.convert_datetime64_to_datetimestruct(&meta, value, &dts)  # 执行转换
    return dts  # 返回datetimestruct结构体

# 生成ISO 8601格式的日期时间字符串
def make_iso_8601_datetime(dt: "datetime"):
    cdef:
        cnp.npy_datetimestruct dts  # datetimestruct结构体
        char result[36]  # 结果字符串数组,长度为36对应NPY_FR_s

    # 将datetime对象的日期时间信息填充到datetimestruct结构体中
    dts.year = dt.year
    dts.month = dt.month
    dts.day = dt.day
    dts.hour = dt.hour
    dts.min = dt.minute
    dts.sec = dt.second
    dts.us = dt.microsecond
    dts.ps = dts.as = 0  # 置ps和as字段为0

    # 生成ISO 8601格式的日期时间字符串
    cnp.make_iso_8601_datetime(
        &dts,
        result,
        sizeof(result),
        0,  # 本地时区标志
        0,  # UTC标志
        cnp.NPY_FR_s,  # 时间基准为秒
        0,  # 时区偏移量
        cnp.NPY_NO_CASTING,
    )
    return result  # 返回生成的日期时间字符串

# 从广播对象中获取multiiter结构体
cdef cnp.broadcast multiiter_from_broadcast_obj(object bcast):
    cdef dict iter_map = {
        1: cnp.PyArray_MultiIterNew1,
        2: cnp.PyArray_MultiIterNew2,
        3: cnp.PyArray_MultiIterNew3,
        4: cnp.PyArray_MultiIterNew4,
        5: cnp.PyArray_MultiIterNew5,
    }
    # 获取bcast对象中的基础数组
    arrays = [x.base for x in bcast.iters]
    # 根据数组数量选择对应的multiiter构造函数,并返回结果
    cdef cnp.broadcast result = iter_map[len(arrays)](*arrays)
    return result  # 返回广播对象的multiiter

# 获取广播对象的大小(元素数量)
def get_multiiter_size(bcast: "broadcast"):
    cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast)
    return multi.size  # 返回广播对象的大小

# 获取广播对象的维度数
def get_multiiter_number_of_dims(bcast: "broadcast"):
    cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast)
    return multi.nd  # 返回广播对象的维度数

# 获取广播对象的当前索引
def get_multiiter_current_index(bcast: "broadcast"):
    cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast)
    return multi.index  # 返回广播对象当前的索引值

# 获取广播对象的迭代器数量
def get_multiiter_num_of_iterators(bcast: "broadcast"):
    cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast)
    return multi.numiter  # 返回广播对象的迭代器数量

# 获取广播对象的形状
def get_multiiter_shape(bcast: "broadcast"):
    cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast)
    # 返回广播对象每个维度的大小构成的元组
    return tuple([multi.dimensions[i] for i in range(bcast.nd)])

# 获取广播对象的迭代器
def get_multiiter_iters(bcast: "broadcast"):
    cdef cnp.broadcast multi = multiiter_from_broadcast_obj(bcast)
    # 创建一个元组,包含了一个生成器表达式的结果,生成器表达式用于获取<cnp.flatiter>multi.iters[i]的值,其中i的取值范围是从0到bcast.numiter-1。
    return tuple([<cnp.flatiter>multi.iters[i] for i in range(bcast.numiter)])
def get_default_integer():
    # 如果默认整数类型是 long,返回 long 类型的数据类型对象
    if cnp.NPY_DEFAULT_INT == cnp.NPY_LONG:
        return cnp.dtype("long")
    # 如果默认整数类型是 intp,返回 intp 类型的数据类型对象
    if cnp.NPY_DEFAULT_INT == cnp.NPY_INTP:
        return cnp.dtype("intp")
    # 默认情况下返回 None
    return None

def conv_intp(cnp.intp_t val):
    # 简单地返回输入的整数值
    return val

def get_dtype_flags(cnp.dtype dtype):
    # 返回给定数据类型的标志属性
    return dtype.flags

cdef cnp.NpyIter* npyiter_from_nditer_obj(object it):
    """A function to create a NpyIter struct from a nditer object.

    This function is only meant for testing purposes and only extracts the
    necessary info from nditer to test the functionality of NpyIter methods
    """
    cdef:
        cnp.NpyIter* cit
        cnp.PyArray_Descr* op_dtypes[3]
        cnp.npy_uint32 op_flags[3]
        cnp.PyArrayObject* ops[3]
        cnp.npy_uint32 flags = 0

    # 根据 nditer 对象的属性设置迭代器的标志位
    if it.has_index:
        flags |= cnp.NPY_ITER_C_INDEX
    if it.has_delayed_bufalloc:
        flags |= cnp.NPY_ITER_BUFFERED | cnp.NPY_ITER_DELAY_BUFALLOC
    if it.has_multi_index:
        flags |= cnp.NPY_ITER_MULTI_INDEX

    # 将所有操作数设置为只读模式
    for i in range(it.nop):
        op_flags[i] = cnp.NPY_ITER_READONLY

    # 获取每个操作数的数据类型和对象
    for i in range(it.nop):
        op_dtypes[i] = cnp.PyArray_DESCR(it.operands[i])
        ops[i] = <cnp.PyArrayObject*>it.operands[i]

    # 创建 NpyIter 对象,用于迭代操作
    cit = cnp.NpyIter_MultiNew(it.nop, &ops[0], flags, cnp.NPY_KEEPORDER,
                               cnp.NPY_NO_CASTING, &op_flags[0],
                               <cnp.PyArray_Descr**>NULL)
    return cit

def get_npyiter_size(it: "nditer"):
    # 创建 NpyIter 对象并获取其迭代的大小
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    result = cnp.NpyIter_GetIterSize(cit)
    cnp.NpyIter_Deallocate(cit)
    return result

def get_npyiter_ndim(it: "nditer"):
    # 创建 NpyIter 对象并获取其维度数
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    result = cnp.NpyIter_GetNDim(cit)
    cnp.NpyIter_Deallocate(cit)
    return result

def get_npyiter_nop(it: "nditer"):
    # 创建 NpyIter 对象并获取其操作数数量
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    result = cnp.NpyIter_GetNOp(cit)
    cnp.NpyIter_Deallocate(cit)
    return result

def get_npyiter_operands(it: "nditer"):
    # 创建 NpyIter 对象并获取其操作数的 ndarray 对象
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    try:
        arr = cnp.NpyIter_GetOperandArray(cit)
        return tuple([<cnp.ndarray>arr[i] for i in range(it.nop)])
    finally:
        cnp.NpyIter_Deallocate(cit)

def get_npyiter_itviews(it: "nditer"):
    # 创建 NpyIter 对象并获取其操作数的迭代视图
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    result = tuple([cnp.NpyIter_GetIterView(cit, i) for i in range(it.nop)])
    cnp.NpyIter_Deallocate(cit)
    return result

def get_npyiter_dtypes(it: "nditer"):
    # 创建 NpyIter 对象并获取其操作数的数据类型
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    try:
        arr = cnp.NpyIter_GetDescrArray(cit)
        return tuple([<cnp.dtype>arr[i] for i in range(it.nop)])
    finally:
        cnp.NpyIter_Deallocate(cit)

def npyiter_has_delayed_bufalloc(it: "nditer"):
    # 创建 NpyIter 对象并检查其是否具有延迟缓冲分配
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    result = cnp.NpyIter_HasDelayedBufAlloc(cit)
    # 调用 cnp 模块中的 NpyIter_Deallocate 函数,用于释放 NpyIter 对象占用的资源
    cnp.NpyIter_Deallocate(cit)
    # 返回 result 变量作为函数的返回结果
    return result
# 检查给定的 nditer 对象是否有索引
def npyiter_has_index(it: "nditer"):
    # 从 nditer 对象获取相应的 NpyIter 指针
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    # 调用 C 函数检查 NpyIter 对象是否有索引
    result = cnp.NpyIter_HasIndex(cit)
    # 释放 NpyIter 对象占用的内存
    cnp.NpyIter_Deallocate(cit)
    return result


# 检查给定的 nditer 对象是否有多重索引
def npyiter_has_multi_index(it: "nditer"):
    # 从 nditer 对象获取相应的 NpyIter 指针
    cdef cnp.NpyIter* cit = npyiter_from_nditer_obj(it)
    # 调用 C 函数检查 NpyIter 对象是否有多重索引
    result = cnp.NpyIter_HasMultiIndex(cit)
    # 释放 NpyIter 对象占用的内存
    cnp.NpyIter_Deallocate(cit)
    return result


# 检查给定的 nditer 对象是否已经迭代完成
def npyiter_has_finished(it: "nditer"):
    cdef cnp.NpyIter* cit
    try:
        # 尝试从 nditer 对象获取相应的 NpyIter 指针
        cit = npyiter_from_nditer_obj(it)
        # 将 NpyIter 定位到指定的迭代索引
        cnp.NpyIter_GotoIterIndex(cit, it.index)
        # 检查迭代索引是否小于迭代的总大小,并返回结果
        return not (cnp.NpyIter_GetIterIndex(cit) < cnp.NpyIter_GetIterSize(cit))
    finally:
        # 无论如何都要释放 NpyIter 对象占用的内存
        cnp.NpyIter_Deallocate(cit)


# 编译并测试填充字节的功能,用于回归测试 gh-25878
def compile_fillwithbyte():
    # 定义一个长度为 2 的 npy_intp 类型的数组 dims
    cdef cnp.npy_intp dims[2]
    dims = (1, 2)
    # 创建一个形状为 dims,类型为 NPY_UINT8 的全零数组 pos
    pos = cnp.PyArray_ZEROS(2, dims, cnp.NPY_UINT8, 0)
    # 调用 C 函数填充数组 pos 的每个元素为指定的字节值
    cnp.PyArray_FILLWBYTE(pos, 1)
    return pos


# 在 C 编译模式下增加复数结构数组的实部和虚部
def inc2_cfloat_struct(cnp.ndarray[cnp.cfloat_t] arr):
    # 只在 C 编译模式下有效,增加数组 arr 中索引为 1 的元素的实部和虚部
    arr[1].real += 1
    arr[1].imag += 1
    # 在所有编译模式下都有效,增加数组 arr 中索引为 1 的元素的实部和虚部
    arr[1].real = arr[1].real + 1
    arr[1].imag = arr[1].imag + 1

.\numpy\numpy\_core\tests\examples\cython\setup.py

"""
Provide python-space access to the functions exposed in numpy/__init__.pxd
for testing.
"""

# 导入所需的库
import numpy as np  # 导入NumPy库
from distutils.core import setup  # 导入setup函数,用于设置和安装扩展
from Cython.Build import cythonize  # 导入cythonize函数,用于将Cython代码编译为扩展模块
from setuptools.extension import Extension  # 导入Extension类,用于定义扩展模块
import os  # 导入os模块,用于操作系统相关功能

# 定义宏定义列表
macros = [
    ("NPY_NO_DEPRECATED_API", 0),  # 不使用已弃用的API
    # 要求NumPy版本至少为1.25以测试日期时间功能的新增
    ("NPY_TARGET_VERSION", "NPY_2_0_API_VERSION"),
]

# 定义Extension对象
checks = Extension(
    "checks",  # 扩展模块名为"checks"
    sources=[os.path.join('.', "checks.pyx")],  # 扩展模块的源文件为当前目录下的"checks.pyx"
    include_dirs=[np.get_include()],  # 包含NumPy头文件目录
    define_macros=macros,  # 使用前面定义的宏定义列表
)

# 将定义好的Extension对象放入列表中
extensions = [checks]

# 调用setup函数,配置和安装扩展模块
setup(
    ext_modules=cythonize(extensions)  # 将Extension对象列表传递给cythonize函数进行编译
)

.\numpy\numpy\_core\tests\examples\limited_api\limited_api1.c

#define Py_LIMITED_API 0x03060000

# 定义了 Py_LIMITED_API 宏,指定了 Python 的限制 API 版本为 0x03060000


#include <Python.h>
#include <numpy/arrayobject.h>
#include <numpy/ufuncobject.h>

# 包含了必要的头文件:Python.h 是 Python C API 的主头文件,arrayobject.h 和 ufuncobject.h 是 NumPy 数组对象和通用函数对象的头文件


static PyModuleDef moduledef = {
    .m_base = PyModuleDef_HEAD_INIT,
    .m_name = "limited_api1"
};

# 定义了名为 moduledef 的静态变量,类型为 PyModuleDef,初始化了其中的 m_base 和 m_name 字段。m_base 使用了 PyModuleDef_HEAD_INIT 宏进行初始化,m_name 设置为字符串 "limited_api1"


PyMODINIT_FUNC PyInit_limited_api1(void)
{
    import_array();
    import_umath();
    return PyModule_Create(&moduledef);
}

# PyMODINIT_FUNC 表明这是一个 Python 模块初始化函数,名称为 PyInit_limited_api1。函数内部首先调用 import_array() 和 import_umath() 函数来导入 NumPy 的数组和通用数学函数模块。然后使用 PyModule_Create(&moduledef) 来创建一个 Python 模块对象,返回给 Python 解释器。

.\numpy\numpy\_core\tests\examples\limited_api\limited_api2.pyx

#cython: language_level=3
# 设置 Cython 的语言级别为 3,以支持较新的语言特性和语法

"""
Make sure cython can compile in limited API mode (see meson.build)
"""
# 引入 NumPy 的头文件中的数组对象声明
cdef extern from "numpy/arrayobject.h":
    pass
# 引入 NumPy 的标量数组头文件中的声明
cdef extern from "numpy/arrayscalars.h":
    pass

.\numpy\numpy\_core\tests\examples\limited_api\setup.py

"""
Build an example package using the limited Python C API.
"""

# 导入必要的库
import numpy as np  # 导入 NumPy 库
from setuptools import setup, Extension  # 导入 setuptools 库中的 setup 和 Extension 函数
import os  # 导入操作系统相关的库

# 定义宏,用于 Extension 对象的初始化
macros = [("NPY_NO_DEPRECATED_API", 0), ("Py_LIMITED_API", "0x03060000")]

# 创建 Extension 对象 limited_api
limited_api = Extension(
    "limited_api",  # 扩展模块名为 "limited_api"
    sources=[os.path.join('.', "limited_api.c")],  # 指定源文件为当前目录下的 limited_api.c
    include_dirs=[np.get_include()],  # 包含 NumPy 库的头文件目录
    define_macros=macros,  # 定义预处理宏
)

# 将 limited_api 加入到 extensions 列表中
extensions = [limited_api]

# 调用 setuptools 的 setup 函数,配置扩展模块
setup(
    ext_modules=extensions  # 指定扩展模块列表
)

.\numpy\numpy\_core\tests\test_abc.py

# 导入需要的模块
from numpy.testing import assert_

import numbers

import numpy as np
from numpy._core.numerictypes import sctypes
# 测试用例类
class TestABC:
    # 测试抽象类
    def test_abstract(self):
        # 判断np.number是否是numbers.Number的子类
        assert_(issubclass(np.number, numbers.Number))

        # 判断np.inexact是否是numbers.Complex的子类
        assert_(issubclass(np.inexact, numbers.Complex))
        # 判断np.complexfloating是否是numbers.Complex的子类
        assert_(issubclass(np.complexfloating, numbers.Complex))
        # 判断np.floating是否是numbers.Real的子类
        assert_(issubclass(np.floating, numbers.Real))

        # 判断np.integer是否是numbers.Integral的子类
        assert_(issubclass(np.integer, numbers.Integral))
        # 判断np.signedinteger是否是numbers.Integral的子类
        assert_(issubclass(np.signedinteger, numbers.Integral))
        # 判断np.unsignedinteger是否是numbers.Integral的子类
        assert_(issubclass(np.unsignedinteger, numbers.Integral))

    # 测试浮点数类型
    def test_floats(self):
        # 遍历浮点数类型
        for t in sctypes['float']:
            # 判断是否是numbers.Real的实例
            assert_(isinstance(t(), numbers.Real),
                    f"{t.__name__} is not instance of Real")
            # 判断是否是numbers.Real的子类
            assert_(issubclass(t, numbers.Real),
                    f"{t.__name__} is not subclass of Real")
            # 判断不是numbers.Rational的实例
            assert_(not isinstance(t(), numbers.Rational),
                    f"{t.__name__} is instance of Rational")
            # 判断不是numbers.Rational的子类
            assert_(not issubclass(t, numbers.Rational),
                    f"{t.__name__} is subclass of Rational")

    # 测试复数类型
    def test_complex(self):
        # 遍历复数类型
        for t in sctypes['complex']:
            # 判断是否是numbers.Complex的实例
            assert_(isinstance(t(), numbers.Complex),
                    f"{t.__name__} is not instance of Complex")
            # 判断是否是numbers.Complex的子类
            assert_(issubclass(t, numbers.Complex),
                    f"{t.__name__} is not subclass of Complex")
            # 判断不是numbers.Real的实例
            assert_(not isinstance(t(), numbers.Real),
                    f"{t.__name__} is instance of Real")
            # 判断不是numbers.Real的子类
            assert_(not issubclass(t, numbers.Real),
                    f"{t.__name__} is subclass of Real")

    # 测试整数类型
    def test_int(self):
        # 遍历整数类型
        for t in sctypes['int']:
            # 判断是否是numbers.Integral的实例
            assert_(isinstance(t(), numbers.Integral),
                    f"{t.__name__} is not instance of Integral")
            # 判断是否是numbers.Integral的子类
            assert_(issubclass(t, numbers.Integral),
                    f"{t.__name__} is not subclass of Integral")

    # 测试无符号整数类型
    def test_uint(self):
        # 遍历无符号整数类型
        for t in sctypes['uint']:
            # 判断是否是numbers.Integral的实例
            assert_(isinstance(t(), numbers.Integral),
                    f"{t.__name__} is not instance of Integral")
            # 判断是否是numbers.Integral的子类
            assert_(issubclass(t, numbers.Integral),
                    f"{t.__name__} is not subclass of Integral")

.\numpy\numpy\_core\tests\test_api.py

# 导入 sys 模块,用于获取系统相关信息
import sys

# 导入 numpy 库,并将其命名为 np
import numpy as np

# 导入 numpy 内部的 umath 模块,用于数学运算
import numpy._core.umath as ncu

# 导入 numpy 内部的 _rational_tests 模块中的 rational 对象
from numpy._core._rational_tests import rational

# 导入 pytest 库,用于编写和运行测试用例
import pytest

# 导入 numpy.testing 模块中的多个断言函数,用于测试 numpy 数组的行为和属性
from numpy.testing import (
     assert_, assert_equal, assert_array_equal, assert_raises, assert_warns,
     HAS_REFCOUNT
    )


# 定义测试函数 test_array_array
def test_array_array():
    # 获取 Python 内置对象 object 的类型
    tobj = type(object)

    # 创建一个形状为 (1, 1) 的 numpy 数组,元素值为 1.0,数据类型为 np.float64
    ones11 = np.ones((1, 1), np.float64)

    # 获取 ones11 对象的类型
    tndarray = type(ones11)

    # 测试 np.array 函数对于 numpy 数组的行为
    assert_equal(np.array(ones11, dtype=np.float64), ones11)

    # 如果支持引用计数(HAS_REFCOUNT 为 True),则测试引用计数的变化
    if HAS_REFCOUNT:
        old_refcount = sys.getrefcount(tndarray)
        np.array(ones11)
        assert_equal(old_refcount, sys.getrefcount(tndarray))

    # 测试 np.array 函数对于 None 的行为
    assert_equal(np.array(None, dtype=np.float64),
                 np.array(np.nan, dtype=np.float64))

    # 如果支持引用计数(HAS_REFCOUNT 为 True),则测试引用计数的变化
    if HAS_REFCOUNT:
        old_refcount = sys.getrefcount(tobj)
        np.array(None, dtype=np.float64)
        assert_equal(old_refcount, sys.getrefcount(tobj))

    # 测试 np.array 函数对于标量的行为
    assert_equal(np.array(1.0, dtype=np.float64),
                 np.ones((), dtype=np.float64))

    # 如果支持引用计数(HAS_REFCOUNT 为 True),则测试引用计数的变化
    if HAS_REFCOUNT:
        old_refcount = sys.getrefcount(np.float64)
        np.array(np.array(1.0, dtype=np.float64), dtype=np.float64)
        assert_equal(old_refcount, sys.getrefcount(np.float64))

    # 测试 np.array 函数对于字符串的行为
    S2 = np.dtype((bytes, 2))
    S3 = np.dtype((bytes, 3))
    S5 = np.dtype((bytes, 5))
    assert_equal(np.array(b"1.0", dtype=np.float64),
                 np.ones((), dtype=np.float64))
    assert_equal(np.array(b"1.0").dtype, S3)
    assert_equal(np.array(b"1.0", dtype=bytes).dtype, S3)
    assert_equal(np.array(b"1.0", dtype=S2), np.array(b"1."))  # 转换为指定长度的 bytes 类型
    assert_equal(np.array(b"1", dtype=S5), np.ones((), dtype=S5))  # 转换为指定长度的 bytes 类型

    # 测试 np.array 函数对于 Unicode 字符串的行为
    U2 = np.dtype((str, 2))
    U3 = np.dtype((str, 3))
    U5 = np.dtype((str, 5))
    assert_equal(np.array("1.0", dtype=np.float64),
                 np.ones((), dtype=np.float64))
    assert_equal(np.array("1.0").dtype, U3)
    assert_equal(np.array("1.0", dtype=str).dtype, U3)
    assert_equal(np.array("1.0", dtype=U2), np.array(str("1.")))  # 转换为指定长度的 str 类型
    assert_equal(np.array("1", dtype=U5), np.ones((), dtype=U5))  # 转换为指定长度的 str 类型

    # 获取内置模块 __builtins__ 中的 get 方法,并断言其存在
    builtins = getattr(__builtins__, '__dict__', __builtins__)
    assert_(hasattr(builtins, 'get'))

    # 测试 np.array 函数对于 memoryview 对象的行为
    dat = np.array(memoryview(b'1.0'), dtype=np.float64)
    assert_equal(dat, [49.0, 46.0, 48.0])  # 转换为 float64 数组
    assert_(dat.dtype.type is np.float64)

    dat = np.array(memoryview(b'1.0'))
    assert_equal(dat, [49, 46, 48])  # 转换为 uint8 数组
    assert_(dat.dtype.type is np.uint8)

    # 测试 np.array 函数对于具有 array interface 的对象的行为
    a = np.array(100.0, dtype=np.float64)
    o = type("o", (object,),
             dict(__array_interface__=a.__array_interface__))
    assert_equal(np.array(o, dtype=np.float64), a)

    # 测试 np.array 函数对于具有 array_struct interface 的对象的行为
    a = np.array([(1, 4.0, 'Hello'), (2, 6.0, 'World')],
                 dtype=[('f0', int), ('f1', float), ('f2', str)])
    o = type("o", (object,),
             dict(__array_struct__=a.__array_struct__))
    # 对比两个对象 o 和 a 的字节表示是否相等
    assert_equal(bytes(np.array(o).data), bytes(a.data))

    # 定义一个自定义的 __array__ 方法,返回一个包含单个元素 100.0 的 numpy 数组
    def custom__array__(self, dtype=None, copy=None):
        return np.array(100.0, dtype=dtype, copy=copy)

    # 创建一个名为 o 的类实例,该实例包含自定义的 __array__ 方法
    o = type("o", (object,), dict(__array__=custom__array__))()

    # 断言使用 np.float64 类型创建 o 的 numpy 数组与给定的 np.float64 数组相等
    assert_equal(np.array(o, dtype=np.float64), np.array(100.0, np.float64))

    # 初始化一个嵌套列表 nested,包含 1.5,循环添加维度直到达到 ncu.MAXDIMS 上限
    nested = 1.5
    for i in range(ncu.MAXDIMS):
        nested = [nested]

    # 尝试将 nested 转换为 numpy 数组,不应该引发错误
    np.array(nested)

    # 当尝试使用包含嵌套列表 nested 的列表创建 numpy 数组时,应该引发 ValueError
    assert_raises(ValueError, np.array, [nested], dtype=np.float64)

    # 使用 None 初始化的列表,期望结果为包含 np.nan 的 numpy 数组
    assert_equal(np.array([None] * 10, dtype=np.float32),
                 np.full((10,), np.nan, dtype=np.float32))
    assert_equal(np.array([[None]] * 10, dtype=np.float32),
                 np.full((10, 1), np.nan, dtype=np.float32))
    assert_equal(np.array([[None] * 10], dtype=np.float32),
                 np.full((1, 10), np.nan, dtype=np.float32))
    assert_equal(np.array([[None] * 10] * 10, dtype=np.float32),
                 np.full((10, 10), np.nan, dtype=np.float32))

    # 使用 None 初始化的列表,期望结果为包含 np.nan 的 numpy 数组,但数据类型为 np.float64
    assert_equal(np.array([None] * 10, dtype=np.float64),
                 np.full((10,), np.nan, dtype=np.float64))
    assert_equal(np.array([[None]] * 10, dtype=np.float64),
                 np.full((10, 1), np.nan, dtype=np.float64))
    assert_equal(np.array([[None] * 10], dtype=np.float64),
                 np.full((1, 10), np.nan, dtype=np.float64))
    assert_equal(np.array([[None] * 10] * 10, dtype=np.float64),
                 np.full((10, 10), np.nan, dtype=np.float64))

    # 使用 1.0 初始化的列表,期望结果为包含 1.0 的 numpy 数组,数据类型为 np.float64
    assert_equal(np.array([1.0] * 10, dtype=np.float64),
                 np.ones((10,), dtype=np.float64))
    assert_equal(np.array([[1.0]] * 10, dtype=np.float64),
                 np.ones((10, 1), dtype=np.float64))
    assert_equal(np.array([[1.0] * 10], dtype=np.float64),
                 np.ones((1, 10), dtype=np.float64))
    assert_equal(np.array([[1.0] * 10] * 10, dtype=np.float64),
                 np.ones((10, 10), dtype=np.float64))

    # 使用 None 或 1.0 初始化的元组,期望结果与相应的列表初始化相同
    assert_equal(np.array((None,) * 10, dtype=np.float64),
                 np.full((10,), np.nan, dtype=np.float64))
    assert_equal(np.array([(None,)] * 10, dtype=np.float64),
                 np.full((10, 1), np.nan, dtype=np.float64))
    assert_equal(np.array([(None,) * 10], dtype=np.float64),
                 np.full((1, 10), np.nan, dtype=np.float64))
    assert_equal(np.array([(None,) * 10] * 10, dtype=np.float64),
                 np.full((10, 10), np.nan, dtype=np.float64))

    assert_equal(np.array((1.0,) * 10, dtype=np.float64),
                 np.ones((10,), dtype=np.float64))
    assert_equal(np.array([(1.0,)] * 10, dtype=np.float64),
                 np.ones((10, 1), dtype=np.float64))
    # 断言:验证生成的 NumPy 数组是否与预期的一维全 1 数组相等,数据类型为 np.float64
    assert_equal(np.array([(1.0,) * 10], dtype=np.float64),
                 np.ones((1, 10), dtype=np.float64))
    
    # 断言:验证生成的 NumPy 数组是否与预期的二维全 1 数组相等,数据类型为 np.float64
    assert_equal(np.array([(1.0,) * 10] * 10, dtype=np.float64),
                 np.ones((10, 10), dtype=np.float64))
# 使用 pytest.mark.parametrize 装饰器,定义一个参数化测试函数,测试不同情况下的数组转换行为
@pytest.mark.parametrize("array", [True, False])
def test_array_impossible_casts(array):
    # 所有内置类型理论上都可以强制转换,但用户自定义类型不一定能够。
    # 创建一个 rational 类型对象 rt,分子为 1,分母为 2
    rt = rational(1, 2)
    # 如果 array 为 True,则将 rt 转换为 NumPy 数组
    if array:
        rt = np.array(rt)
    # 使用 assert_raises 检查 TypeError 是否被抛出
    with assert_raises(TypeError):
        np.array(rt, dtype="M8")


# 定义一个测试函数,测试 NumPy 数组的 astype 方法
def test_array_astype():
    # 创建一个包含 0 到 5 的浮点数数组 a,形状为 2x3
    a = np.arange(6, dtype='f4').reshape(2, 3)
    # 默认行为:允许不安全的类型转换,保持内存布局,总是复制。
    # 将数组 a 转换为整数类型 'i4'
    b = a.astype('i4')
    assert_equal(a, b)
    assert_equal(b.dtype, np.dtype('i4'))
    assert_equal(a.strides, b.strides)
    
    # 将数组 a 转置后再转换为整数类型 'i4'
    b = a.T.astype('i4')
    assert_equal(a.T, b)
    assert_equal(b.dtype, np.dtype('i4'))
    assert_equal(a.T.strides, b.strides)
    
    # 将数组 a 转换回浮点数类型 'f4'
    b = a.astype('f4')
    assert_equal(a, b)
    assert_(not (a is b))

    # copy=False 参数跳过复制操作
    b = a.astype('f4', copy=False)
    assert_(a is b)

    # order 参数允许覆盖内存布局,如果布局错误则强制复制
    b = a.astype('f4', order='F', copy=False)
    assert_equal(a, b)
    assert_(not (a is b))
    assert_(b.flags.f_contiguous)

    b = a.astype('f4', order='C', copy=False)
    assert_equal(a, b)
    assert_(a is b)
    assert_(b.flags.c_contiguous)

    # casting 参数允许捕获不良类型转换
    b = a.astype('c8', casting='safe')
    assert_equal(a, b)
    assert_equal(b.dtype, np.dtype('c8'))

    assert_raises(TypeError, a.astype, 'i4', casting='safe')

    # subok=False 参数传递非子类化数组
    b = a.astype('f4', subok=0, copy=False)
    assert_(a is b)

    # 定义一个名为 MyNDArray 的子类
    class MyNDArray(np.ndarray):
        pass

    a = np.array([[0, 1, 2], [3, 4, 5]], dtype='f4').view(MyNDArray)

    # subok=True 参数传递子类化数组
    b = a.astype('f4', subok=True, copy=False)
    assert_(a is b)

    # subok=True 是默认行为,在类型转换时创建子类型
    b = a.astype('i4', copy=False)
    assert_equal(a, b)
    assert_equal(type(b), MyNDArray)

    # subok=False 永远不会返回子类化数组
    b = a.astype('f4', subok=False, copy=False)
    assert_equal(a, b)
    assert_(not (a is b))
    assert_(type(b) is not MyNDArray)

    # 确保从字符串对象转换为固定长度字符串时不会截断。
    a = np.array([b'a'*100], dtype='O')
    b = a.astype('S')
    assert_equal(a, b)
    assert_equal(b.dtype, np.dtype('S100'))
    a = np.array(['a'*100], dtype='O')
    b = a.astype('U')
    assert_equal(a, b)
    assert_equal(b.dtype, np.dtype('U100'))

    # 对于长度小于 64 个字符的字符串,进行相同的测试
    a = np.array([b'a'*10], dtype='O')
    b = a.astype('S')
    assert_equal(a, b)
    assert_equal(b.dtype, np.dtype('S10'))
    a = np.array(['a'*10], dtype='O')
    b = a.astype('U')
    assert_equal(a, b)
    assert_equal(b.dtype, np.dtype('U10'))

    # 将整数对象转换为字符串类型的固定长度字符串
    a = np.array(123456789012345678901234567890, dtype='O').astype('S')
    # 使用 numpy.testing.assert_array_equal 函数比较数组 a 和给定的数组是否相等
    assert_array_equal(a, np.array(b'1234567890' * 3, dtype='S30'))
    
    # 创建一个包含很长整数的 numpy 数组 a,使用对象类型 'O',然后将其转换为 Unicode 字符串类型 'U'
    a = np.array(123456789012345678901234567890, dtype='O').astype('U')
    # 使用 numpy.testing.assert_array_equal 函数比较数组 a 和给定的 Unicode 字符串数组是否相等
    assert_array_equal(a, np.array('1234567890' * 3, dtype='U30'))
    
    # 创建一个包含很长整数的 numpy 数组,使用对象类型 'O',然后将其转换为字节字符串类型 'S'
    a = np.array([123456789012345678901234567890], dtype='O').astype('S')
    # 使用 numpy.testing.assert_array_equal 函数比较数组 a 和给定的字节字符串数组是否相等
    assert_array_equal(a, np.array(b'1234567890' * 3, dtype='S30'))
    
    # 创建一个很长整数的 numpy 数组,使用字符串类型 'S'
    a = np.array(123456789012345678901234567890, dtype='S')
    # 使用 numpy.testing.assert_array_equal 函数比较数组 a 和给定的字节字符串数组是否相等
    assert_array_equal(a, np.array(b'1234567890' * 3, dtype='S30'))
    
    # 创建一个 Unicode 字符串数组 a,包含特定的 Unicode 字符
    a = np.array('a\u0140', dtype='U')
    # 使用 numpy.ndarray 构造函数创建一个新的数组 b,从给定的缓冲区 a 中创建,数据类型为 uint32,形状为 (2,)
    b = np.ndarray(buffer=a, dtype='uint32', shape=2)
    # 使用 assert_ 断言检查数组 b 的大小是否为 2
    assert_(b.size == 2)
    
    # 创建一个整数数组 a,包含单个元素 1000,数据类型为 'i4'
    a = np.array([1000], dtype='i4')
    # 使用 assert_raises 断言检查尝试将数组 a 的元素转换为 'S1' 类型时是否引发了 TypeError 异常
    assert_raises(TypeError, a.astype, 'S1', casting='safe')
    
    # 创建一个整数数组 a,包含单个元素 1000,数据类型为 'i4'
    a = np.array(1000, dtype='i4')
    # 使用 assert_raises 断言检查尝试将数组 a 转换为 'U1' 类型时是否引发了 TypeError 异常
    assert_raises(TypeError, a.astype, 'U1', casting='safe')
    
    # 对于问题 gh-24023,使用 assert_raises 断言检查调用 a.astype() 函数时是否引发了 TypeError 异常
    assert_raises(TypeError, a.astype)
# 使用 pytest.mark.parametrize 装饰器为 test_array_astype_to_string_discovery_empty 函数参数化,参数为字符串 "S" 和 "U"
@pytest.mark.parametrize("dt", ["S", "U"])
def test_array_astype_to_string_discovery_empty(dt):
    # 引用 GitHub issue 19085
    arr = np.array([""], dtype=object)
    # 注意,itemsize 是 `0 -> 1` 的逻辑,应该会改变。
    # 重要的是测试不报错。
    assert arr.astype(dt).dtype.itemsize == np.dtype(f"{dt}1").itemsize

    # 使用 np.can_cast 检查相同的情况(因为它接受数组)
    assert np.can_cast(arr, dt, casting="unsafe")
    assert not np.can_cast(arr, dt, casting="same_kind")
    # 同样也适用于对象作为描述符:
    assert np.can_cast("O", dt, casting="unsafe")

# 使用 pytest.mark.parametrize 装饰器为 test_array_astype_to_void 函数参数化,参数为字符串 "d", "f", "S13", "U32"
@pytest.mark.parametrize("dt", ["d", "f", "S13", "U32"])
def test_array_astype_to_void(dt):
    dt = np.dtype(dt)
    arr = np.array([], dtype=dt)
    assert arr.astype("V").dtype.itemsize == dt.itemsize

# test_object_array_astype_to_void 函数不接受参数,测试对象数组转换为 void 类型
def test_object_array_astype_to_void():
    # 与 `test_array_astype_to_void` 不同,因为对象数组被检查。
    # 默认的 void 是 "V8"(8 是 double 的长度)
    arr = np.array([], dtype="O").astype("V")
    assert arr.dtype == "V8"

# 使用 pytest.mark.parametrize 装饰器为 test_array_astype_warning 函数参数化,参数为 np._core.sctypes['uint'] + np._core.sctypes['int'] + np._core.sctypes['float'] 的各个类型
@pytest.mark.parametrize("t", np._core.sctypes['uint'] + np._core.sctypes['int'] + np._core.sctypes['float'])
def test_array_astype_warning(t):
    # 测试从复数到浮点数或整数的转换时的 ComplexWarning
    a = np.array(10, dtype=np.complex128)
    assert_warns(np.exceptions.ComplexWarning, a.astype, t)

# 使用 pytest.mark.parametrize 装饰器为 test_string_to_boolean_cast 函数参数化,参数为不同的 dtype 和 out_dtype 组合
@pytest.mark.parametrize(["dtype", "out_dtype"],
        [(np.bytes_, np.bool),
         (np.str_, np.bool),
         (np.dtype("S10,S9"), np.dtype("?,?")),
         (np.dtype("S7,U9"), np.dtype("?,?"))])
def test_string_to_boolean_cast(dtype, out_dtype):
    # 只有最后两个(空)字符串是假值(`\0` 被剥离):
    arr = np.array(
            ["10", "10\0\0\0", "0\0\0", "0", "False", " ", "", "\0"],
            dtype=dtype)
    expected = np.array(
            [True, True, True, True, True, True, False, False],
            dtype=out_dtype)
    assert_array_equal(arr.astype(out_dtype), expected)
    # 因为相似,检查非零行为是否相同(结构体如果所有条目都不为零)
    assert_array_equal(np.nonzero(arr), np.nonzero(expected))

# 使用 pytest.mark.parametrize 装饰器为 test_string_to_complex_cast 函数参数化,参数为不同的 str_type 和 scalar_type 组合
@pytest.mark.parametrize("str_type", [str, bytes, np.str_])
@pytest.mark.parametrize("scalar_type",
        [np.complex64, np.complex128, np.clongdouble])
def test_string_to_complex_cast(str_type, scalar_type):
    value = scalar_type(b"1+3j")
    assert scalar_type(value) == 1+3j
    assert np.array([value], dtype=object).astype(scalar_type)[()] == 1+3j
    assert np.array(value).astype(scalar_type)[()] == 1+3j
    arr = np.zeros(1, dtype=scalar_type)
    arr[0] = value
    assert arr[0] == 1+3j

# 使用 pytest.mark.parametrize 装饰器为 test_none_to_nan_cast 函数参数化,参数为 np.typecodes["AllFloat"] 中的各种 dtype
@pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
def test_none_to_nan_cast(dtype):
    # 注意,在编写此测试时,标量构造函数拒绝 None
    # 创建一个包含一个元素的 NumPy 数组,元素值为 0.0,数据类型为参数 dtype 指定的类型
    arr = np.zeros(1, dtype=dtype)
    # 将数组中第一个元素赋值为 None
    arr[0] = None
    # 使用 NumPy 的函数检查数组中第一个元素是否为 NaN(Not a Number)
    assert np.isnan(arr)[0]
    # 使用 NumPy 创建一个包含单个元素为 None 的数组,并检查该元素是否为 NaN
    assert np.isnan(np.array(None, dtype=dtype))[()]
    # 使用 NumPy 创建一个包含单个元素为 None 的数组,并检查第一个元素是否为 NaN
    assert np.isnan(np.array([None], dtype=dtype))[0]
    # 将 None 转换为 dtype 指定的数据类型后,使用 NumPy 检查该元素是否为 NaN
    assert np.isnan(np.array(None).astype(dtype))[()]
# 定义一个测试函数,用于测试 np.copyto() 函数的不同用法和参数组合
def test_copyto_fromscalar():
    # 创建一个包含6个单精度浮点数的 NumPy 数组,形状为 (2, 3)
    a = np.arange(6, dtype='f4').reshape(2, 3)

    # 简单的复制操作,将标量值 1.5 复制到数组 a 中的所有元素
    np.copyto(a, 1.5)
    # 断言数组 a 中的所有元素是否都等于 1.5
    assert_equal(a, 1.5)

    # 将标量值 2.5 复制到数组 a 的转置矩阵中的所有元素
    np.copyto(a.T, 2.5)
    # 断言数组 a 中的所有元素是否都等于 2.5
    assert_equal(a, 2.5)

    # 使用掩码进行复制操作,将标量值 3.5 复制到数组 a 中的特定位置
    mask = np.array([[0, 1, 0], [0, 0, 1]], dtype='?')
    np.copyto(a, 3.5, where=mask)
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[2.5, 3.5, 2.5], [2.5, 2.5, 3.5]])

    # 再次使用不同的掩码进行复制操作,将标量值 4.5 复制到数组 a 的转置矩阵中的特定位置
    mask = np.array([[0, 1], [1, 1], [1, 0]], dtype='?')
    np.copyto(a.T, 4.5, where=mask)
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[2.5, 4.5, 4.5], [4.5, 4.5, 3.5]])

# 定义另一个测试函数,用于测试 np.copyto() 的更多用法和参数组合
def test_copyto():
    # 创建一个包含6个32位整数的 NumPy 数组,形状为 (2, 3)
    a = np.arange(6, dtype='i4').reshape(2, 3)

    # 简单的复制操作,将指定数组的值复制到数组 a 中
    np.copyto(a, [[3, 1, 5], [6, 2, 1]])
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[3, 1, 5], [6, 2, 1]])

    # 进行重叠复制,将数组 a 的部分区域复制到另一部分区域
    np.copyto(a[:, :2], a[::-1, 1::-1])
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[2, 6, 5], [1, 3, 1]])

    # 测试默认的类型转换规则,预期会引发 TypeError 异常
    assert_raises(TypeError, np.copyto, a, 1.5)

    # 使用 'unsafe' 转换模式进行复制,将标量值 1.5 复制到数组 a 中
    np.copyto(a, 1.5, casting='unsafe')
    # 断言数组 a 中的元素是否按预期进行了复制,由于 'unsafe' 模式,1.5 被截断为 1
    assert_equal(a, 1)

    # 使用掩码进行复制操作,将标量值 3 复制到数组 a 中的特定位置
    np.copyto(a, 3, where=[True, False, True])
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[3, 1, 3], [3, 1, 3]])

    # 测试在使用掩码时的类型转换规则,预期会引发 TypeError 异常
    assert_raises(TypeError, np.copyto, a, 3.5, where=[True, False, True])

    # 使用列表形式的掩码进行复制操作,将标量值 4.0 复制到数组 a 中的特定位置
    np.copyto(a, 4.0, casting='unsafe', where=[[0, 1, 1], [1, 0, 0]])
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[3, 4, 4], [4, 1, 3]])

    # 再次进行重叠复制,结合掩码进行复制操作
    np.copyto(a[:, :2], a[::-1, 1::-1], where=[[0, 1], [1, 1]])
    # 断言数组 a 中的元素是否按预期进行了复制
    assert_equal(a, [[3, 4, 4], [4, 3, 3]])

    # 测试 'dst' 参数必须是一个数组,预期会引发 TypeError 异常
    assert_raises(TypeError, np.copyto, [1, 2, 3], [2, 3, 4])

# 定义另一个测试函数,用于测试特定复制场景下的 np.copyto() 行为
def test_copyto_permut():
    # 设置一个较大的填充数值
    pad = 500
    # 创建一个布尔类型的列表,大部分为 True,最后四个为 True
    l = [True] * pad + [True, True, True, True]
    # 创建一个长度为 l 去掉前 pad 部分的 0 数组
    r = np.zeros(len(l)-pad)
    # 创建一个长度为 l 去掉前 pad 部分的 1 数组
    d = np.ones(len(l)-pad)
    # 根据反向掩码创建一个数组
    mask = np.array(l)[pad:]
    # 使用掩码对数组 r 进行复制,以便数组 d 的值

    # 复制到 r 的末尾
    np.copyto(r, d, where=mask[::-1])

    # 测试所有可能掩码的排列组合
    power = 9
    d = np.ones(power)
    for i in range(2**power):
        # 创建一个长度为 power 的全零数组 r
        r = np.zeros(power)
        # 生成掩码列表 l,用于判断每个位是否为1
        l = [(i & x) != 0 for x in range(power)]
        # 将 l 转换为布尔数组 mask
        mask = np.array(l)
        # 根据 mask 复制数组 d 的部分元素到 r 中
        np.copyto(r, d, where=mask)
        # 断言 r 中的元素是否与 l 相等(应为布尔值 True/False)
        assert_array_equal(r == 1, l)
        # 断言 r 中的元素之和是否等于 l 中值为 True 的数量
        assert_equal(r.sum(), sum(l))

        # 将 r 重新初始化为全零数组
        r = np.zeros(power)
        # 根据 mask 的反转复制数组 d 的部分元素到 r 中
        np.copyto(r, d, where=mask[::-1])
        # 断言 r 中的元素是否与 l 的反转相等
        assert_array_equal(r == 1, l[::-1])
        # 断言 r 中的元素之和是否等于 l 反转后值为 True 的数量
        assert_equal(r.sum(), sum(l))

        # 将 r 重新初始化为全零数组
        r = np.zeros(power)
        # 仅复制偶数索引位置的数组 d 的部分元素到 r 中,根据 mask 的条件
        np.copyto(r[::2], d[::2], where=mask[::2])
        # 断言 r 的偶数索引位置的元素是否与 l 的偶数索引位置相等
        assert_array_equal(r[::2] == 1, l[::2])
        # 断言 r 的偶数索引位置的元素之和是否等于 l 的偶数索引位置值为 True 的数量
        assert_equal(r[::2].sum(), sum(l[::2]))

        # 将 r 重新初始化为全零数组
        r = np.zeros(power)
        # 仅复制偶数索引位置的数组 d 的部分元素到 r 中,根据 mask 反转的条件
        np.copyto(r[::2], d[::2], where=mask[::-2])
        # 断言 r 的偶数索引位置的元素是否与 l 的偶数索引位置反转后相等
        assert_array_equal(r[::2] == 1, l[::-2])
        # 断言 r 的偶数索引位置的元素之和是否等于 l 的偶数索引位置反转后值为 True 的数量
        assert_equal(r[::2].sum(), sum(l[::-2]))

        # 遍历每个常量 c,针对 r 进行处理
        for c in [0xFF, 0x7F, 0x02, 0x10]:
            # 将 r 重新初始化为全零数组
            r = np.zeros(power)
            # 将 mask 转换为整数数组 imask,并根据 mask 的值设置对应位置为常量 c
            mask = np.array(l)
            imask = np.array(l).view(np.uint8)
            imask[mask != 0] = c
            # 根据 mask 复制数组 d 的部分元素到 r 中
            np.copyto(r, d, where=mask)
            # 断言 r 中的元素是否与 l 相等
            assert_array_equal(r == 1, l)
            # 断言 r 中的元素之和是否等于 l 中值为 True 的数量
            assert_equal(r.sum(), sum(l))

    # 最后的处理步骤
    r = np.zeros(power)
    # 将数组 d 的所有元素复制到 r 中
    np.copyto(r, d, where=True)
    # 断言 r 中的元素之和是否等于 r 的大小(即所有元素的数量)
    assert_equal(r.sum(), r.size)
    # 将数组 r 初始化为全一数组,数组 d 初始化为全零数组
    r = np.ones(power)
    d = np.zeros(power)
    # 将数组 d 的所有元素复制到数组 r 中(但不改变 r 中为1的位置)
    np.copyto(r, d, where=False)
    # 断言 r 中的元素之和是否等于 r 的大小
    assert_equal(r.sum(), r.size)
# 定义一个测试函数,用于验证数组拷贝操作的顺序性
def test_copy_order():
    # 创建一个形状为 (2, 1, 3, 4) 的数组 a,填充从 0 到 23 的连续整数
    a = np.arange(24).reshape(2, 1, 3, 4)
    # 使用 order='F' 参数按列主序拷贝数组 a,得到数组 b
    b = a.copy(order='F')
    # 创建一个形状为 (2, 1, 4, 3) 的数组 c,填充从 0 到 23 的连续整数,并交换轴 2 和 3
    c = np.arange(24).reshape(2, 1, 4, 3).swapaxes(2, 3)

    # 定义一个内部函数,用于检查拷贝结果的连续性
    def check_copy_result(x, y, ccontig, fcontig, strides=False):
        # 断言 x 和 y 不是同一个对象
        assert_(not (x is y))
        # 断言 x 和 y 的内容相等
        assert_equal(x, y)
        # 断言 x 的标志中 C 连续性为 ccontig
        assert_equal(x.flags.c_contiguous, ccontig)
        # 断言 x 的标志中 F 连续性为 fcontig
        assert_equal(x.flags.f_contiguous, fcontig)

    # 验证数组 a、b 和 c 的初始状态
    assert_(a.flags.c_contiguous)
    assert_(not a.flags.f_contiguous)
    assert_(not b.flags.c_contiguous)
    assert_(b.flags.f_contiguous)
    assert_(not c.flags.c_contiguous)
    assert_(not c.flags.f_contiguous)

    # 使用 order='C' 参数进行拷贝
    res = a.copy(order='C')
    check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
    res = b.copy(order='C')
    check_copy_result(res, b, ccontig=True, fcontig=False, strides=False)
    res = c.copy(order='C')
    check_copy_result(res, c, ccontig=True, fcontig=False, strides=False)
    res = np.copy(a, order='C')
    check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
    res = np.copy(b, order='C')
    check_copy_result(res, b, ccontig=True, fcontig=False, strides=False)
    res = np.copy(c, order='C')
    check_copy_result(res, c, ccontig=True, fcontig=False, strides=False)

    # 使用 order='F' 参数进行拷贝
    res = a.copy(order='F')
    check_copy_result(res, a, ccontig=False, fcontig=True, strides=False)
    res = b.copy(order='F')
    check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
    res = c.copy(order='F')
    check_copy_result(res, c, ccontig=False, fcontig=True, strides=False)
    res = np.copy(a, order='F')
    check_copy_result(res, a, ccontig=False, fcontig=True, strides=False)
    res = np.copy(b, order='F')
    check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
    res = np.copy(c, order='F')
    check_copy_result(res, c, ccontig=False, fcontig=True, strides=False)

    # 使用 order='K' 参数进行拷贝
    res = a.copy(order='K')
    check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
    res = b.copy(order='K')
    check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
    res = c.copy(order='K')
    check_copy_result(res, c, ccontig=False, fcontig=False, strides=True)
    res = np.copy(a, order='K')
    check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
    res = np.copy(b, order='K')
    check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
    res = np.copy(c, order='K')
    check_copy_result(res, c, ccontig=False, fcontig=False, strides=True)

# 定义一个测试函数,用于验证数组的连续性标志
def test_contiguous_flags():
    # 创建一个形状为 (4, 4, 1) 的数组 a,所有元素为 1,并按条件切片
    a = np.ones((4, 4, 1))[::2,:,:]
    # 修改数组 a 的步长
    a.strides = a.strides[:2] + (-123,)
    # 创建一个形状为 (2, 2, 1, 2, 2) 的数组 b,并交换轴 3 和 4
    b = np.ones((2, 2, 1, 2, 2)).swapaxes(3, 4)

    # 定义一个内部函数,用于检查数组的连续性标志
    def check_contig(a, ccontig, fcontig):
        # 断言数组 a 的 C 连续性标志为 ccontig
        assert_(a.flags.c_contiguous == ccontig)
        # 断言数组 a 的 F 连续性标志为 fcontig
        assert_(a.flags.f_contiguous == fcontig)

    # 检查新数组的连续性
    check_contig(a, False, False)
    check_contig(b, False, False)
    # 调用 check_contig 函数,检查空的4维数组是否连续,并要求检查数组的内容是否被复制
    check_contig(np.empty((2, 2, 0, 2, 2)), True, True)
    # 调用 check_contig 函数,检查按列主序存储的数组是否连续,并要求检查数组的内容是否被复制
    check_contig(np.array([[[1], [2]]], order='F'), True, True)
    # 调用 check_contig 函数,检查空的2维数组是否连续,并要求检查数组的内容是否被复制
    check_contig(np.empty((2, 2)), True, False)
    # 调用 check_contig 函数,检查按列主序存储的空的2维数组是否连续,并要求检查数组的内容是否被复制
    check_contig(np.empty((2, 2), order='F'), False, True)

    # 检查 np.array 创建数组时连续标志的正确性:
    check_contig(np.array(a, copy=None), False, False)
    # 检查 np.array 按行主序存储创建数组时连续标志的正确性,并要求不复制数组内容
    check_contig(np.array(a, copy=None, order='C'), True, False)
    # 检查 np.array 创建4维数组时按列主序存储的连续性标志的正确性,并要求不复制数组内容
    check_contig(np.array(a, ndmin=4, copy=None, order='F'), False, True)

    # 检查切片更新连续性标志:
    check_contig(a[0], True, True)
    # 检查切片更新连续性标志,包括步进为4和省略符号
    check_contig(a[None, ::4, ..., None], True, True)
    # 检查切片更新连续性标志,仅限第一个维度的索引为0,其余维度为省略符号
    check_contig(b[0, 0, ...], False, True)
    # 检查切片更新连续性标志,仅限第三维度的切片范围为0:0,其余维度全取
    check_contig(b[:, :, 0:0, :, :], True, True)

    # 测试 ravel 和 squeeze 方法
    # 检查数组通过 ravel 方法展平后的连续性标志
    check_contig(a.ravel(), True, True)
    # 检查通过 squeeze 方法去除维数为1的数组的连续性标志
    check_contig(np.ones((1, 3, 1)).squeeze(), True, True)
# 定义测试函数,用于测试 np.broadcast_arrays() 函数的功能
def test_broadcast_arrays():
    # 创建具有用户定义数据类型 'u4,u4,u4' 的 numpy 数组 a 和 b
    a = np.array([(1, 2, 3)], dtype='u4,u4,u4')
    b = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype='u4,u4,u4')
    # 对数组 a 和 b 进行广播,得到广播后的结果
    result = np.broadcast_arrays(a, b)
    # 断言第一个广播数组的结果与预期结果相等
    assert_equal(result[0], np.array([(1, 2, 3), (1, 2, 3), (1, 2, 3)], dtype='u4,u4,u4'))
    # 断言第二个广播数组的结果与预期结果相等
    assert_equal(result[1], np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype='u4,u4,u4'))

# 使用 pytest 的 parametrize 装饰器定义多组参数化测试
@pytest.mark.parametrize(["shape", "fill_value", "expected_output"],
        [((2, 2), [5.0,  6.0], np.array([[5.0, 6.0], [5.0, 6.0]])),
         ((3, 2), [1.0,  2.0], np.array([[1.0, 2.0], [1.0, 2.0], [1.0,  2.0]]))])
def test_full_from_list(shape, fill_value, expected_output):
    # 使用 np.full() 函数根据指定形状和填充值创建数组
    output = np.full(shape, fill_value)
    # 断言创建的数组与预期输出数组相等
    assert_equal(output, expected_output)

# 定义测试函数,测试 numpy 数组的 astype() 方法中的复制标志
def test_astype_copyflag():
    # 创建一个包含 0 到 9 的整数 numpy 数组 arr
    arr = np.arange(10, dtype=np.intp)

    # 测试使用 copy=True 参数进行类型转换
    res_true = arr.astype(np.intp, copy=True)
    # 断言结果数组不共享内存
    assert not np.shares_memory(arr, res_true)

    # 测试使用 copy=False 参数进行类型转换
    res_false = arr.astype(np.intp, copy=False)
    # 断言结果数组与原始数组共享内存
    assert np.shares_memory(arr, res_false)

    # 测试将整数数组转换为浮点数数组,并使用 copy=False 参数
    res_false_float = arr.astype(np.float64, copy=False)
    # 断言结果数组不共享内存
    assert not np.shares_memory(arr, res_false_float)

    # 测试不允许使用未公开的 _CopyMode 枚举值
    # 断言调用 astype() 方法时会抛出 ValueError 异常
    assert_raises(ValueError, arr.astype, np.float64,
                  copy=np._CopyMode.NEVER)

.\numpy\numpy\_core\tests\test_argparse.py

"""
Tests for the private NumPy argument parsing functionality.
They mainly exists to ensure good test coverage without having to try the
weirder cases on actual numpy functions but test them in one place.

The test function is defined in C to be equivalent to (errors may not always
match exactly, and could be adjusted):

    def func(arg1, /, arg2, *, arg3):
        i = integer(arg1)  # reproducing the 'i' parsing in Python.
        return None
"""

# 导入 pytest 库,用于编写和运行测试用例
import pytest

# 导入 NumPy 库
import numpy as np
# 从 NumPy 的内部模块中导入名为 argparse_example_function 的函数别名 func
from numpy._core._multiarray_tests import argparse_example_function as func


# 定义测试函数 test_invalid_integers,测试无效整数参数的情况
def test_invalid_integers():
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match="integer argument expected, got float"):
        func(1.)
    # 使用 pytest 的断言检查是否会抛出 OverflowError 异常
    with pytest.raises(OverflowError):
        func(2**100)


# 定义测试函数 test_missing_arguments,测试缺少参数的情况
def test_missing_arguments():
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match="missing required positional argument 0"):
        func()
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match="missing required positional argument 0"):
        func(arg2=1, arg3=4)
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match=r"missing required argument 'arg2' \(pos 1\)"):
        func(1, arg3=5)


# 定义测试函数 test_too_many_positional,测试传递过多位置参数的情况
def test_too_many_positional():
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match="takes from 2 to 3 positional arguments but 4 were given"):
        func(1, 2, 3, 4)


# 定义测试函数 test_multiple_values,测试传递多个值的情况
def test_multiple_values():
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match=r"given by name \('arg2'\) and position \(position 1\)"):
        func(1, 2, arg2=3)


# 定义测试函数 test_string_fallbacks,测试字符串参数的回退情况
def test_string_fallbacks():
    # 使用 numpy 的字符串对象测试慢速回退情况
    arg2 = np.str_("arg2")
    missing_arg = np.str_("missing_arg")
    func(1, **{arg2: 3})
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常,且异常信息匹配特定字符串
    with pytest.raises(TypeError,
            match="got an unexpected keyword argument 'missing_arg'"):
        func(2, **{missing_arg: 3})


# 定义测试函数 test_too_many_arguments_method_forwarding,测试方法转发时参数过多的情况
def test_too_many_arguments_method_forwarding():
    # 不直接关联标准参数解析,但有时我们会将方法转发到 Python
    # 这段代码增加了对 `npy_forward_method` 的代码覆盖率
    arr = np.arange(3)
    args = range(1000)
    # 使用 pytest 的断言检查是否会抛出 TypeError 异常
    with pytest.raises(TypeError):
        arr.mean(*args)

.\numpy\numpy\_core\tests\test_arraymethod.py

"""
This file tests the generic aspects of ArrayMethod.  At the time of writing
this is private API, but when added, public API may be added here.
"""

# 导入必要的模块和库
import sys
import types
from typing import Any

# 导入测试框架 pytest
import pytest

# 导入 NumPy 库,并获取私有函数 _get_castingimpl 别名为 get_castingimpl
import numpy as np
from numpy._core._multiarray_umath import _get_castingimpl as get_castingimpl


class TestResolveDescriptors:
    # 测试 resolve_descriptors 函数的错误路径,注意 `casting_unittests` 测试覆盖了非错误路径

    # 获取 casting 实现,主要/唯一的当前用户
    method = get_castingimpl(type(np.dtype("d")), type(np.dtype("f")))

    @pytest.mark.parametrize("args", [
        (True,),  # 不是元组
        ((None,)),  # 元素太少
        ((None, None, None),),  # 元素太多
        ((None, None),),  # 输入 dtype 是 None,无效
        ((np.dtype("d"), True),),  # 输出 dtype 不是 dtype 类型
        ((np.dtype("f"), None),),  # 输入 dtype 与方法不匹配
    ])
    def test_invalid_arguments(self, args):
        # 断言期望抛出 TypeError 异常
        with pytest.raises(TypeError):
            self.method._resolve_descriptors(*args)


class TestSimpleStridedCall:
    # 测试 resolve_descriptors 函数的错误路径,注意 `casting_unittests` 测试覆盖了非错误路径

    # 获取 casting 实现,主要/唯一的当前用户
    method = get_castingimpl(type(np.dtype("d")), type(np.dtype("f")))

    @pytest.mark.parametrize(["args", "error"], [
        ((True,), TypeError),  # 不是元组
        (((None,),), TypeError),  # 元素太少
        ((None, None), TypeError),  # 输入不是数组
        (((None, None, None),), TypeError),  # 元素太多
        (((np.arange(3), np.arange(3)),), TypeError),  # 不正确的 dtype
        (((np.ones(3, dtype=">d"), np.ones(3, dtype="<f")),), TypeError),  # 不支持字节交换
        (((np.ones((2, 2), dtype="d"), np.ones((2, 2), dtype="f")),), ValueError),  # 不是 1-D 数组
        (((np.ones(3, dtype="d"), np.ones(4, dtype="f")),), ValueError),  # 长度不同
        (((np.frombuffer(b"\0x00"*3*2, dtype="d"), np.frombuffer(b"\0x00"*3, dtype="f")),), ValueError),  # 输出不可写
    ])
    def test_invalid_arguments(self, args, error):
        # 断言期望抛出指定异常
        with pytest.raises(error):
            self.method._simple_strided_call(*args)


@pytest.mark.parametrize(
    "cls", [
        np.ndarray, np.recarray, np.char.chararray, np.matrix, np.memmap
    ]
)
class TestClassGetItem:
    def test_class_getitem(self, cls: type[np.ndarray]) -> None:
        """Test `ndarray.__class_getitem__`."""
        # 测试 ndarray.__class_getitem__ 方法
        alias = cls[Any, Any]
        # 断言 alias 是一个泛型别名类型
        assert isinstance(alias, types.GenericAlias)
        # 断言 alias 的原始类型是 cls
        assert alias.__origin__ is cls

    @pytest.mark.parametrize("arg_len", range(4))
    # 定义测试方法 test_subscript_tup,用于测试给定类型 cls 的元组访问
    # cls 参数指定要测试的 np.ndarray 类型
    # arg_len 参数指定元组的长度
    def test_subscript_tup(self, cls: type[np.ndarray], arg_len: int) -> None:
        # 创建一个由 Any 类型组成的元组 arg_tup,长度为 arg_len
        arg_tup = (Any,) * arg_len
        # 如果 arg_len 为 1 或 2,则断言 cls[arg_tup] 是有效的访问方式
        if arg_len in (1, 2):
            assert cls[arg_tup]
        else:
            # 否则,生成匹配消息,说明参数数量过少或过多
            match = f"Too {'few' if arg_len == 0 else 'many'} arguments"
            # 使用 pytest 来断言会抛出 TypeError 异常,并匹配指定的 match 消息
            with pytest.raises(TypeError, match=match):
                cls[arg_tup]

.\numpy\numpy\_core\tests\test_arrayobject.py

# 导入 pytest 库,用于测试框架
import pytest

# 导入 numpy 库,并导入 assert_array_equal 函数用于比较数组是否相等
import numpy as np
from numpy.testing import assert_array_equal


# 定义测试函数,验证当数组维度小于 2 时,转置操作会引发 ValueError 异常
def test_matrix_transpose_raises_error_for_1d():
    msg = "matrix transpose with ndim < 2 is undefined"
    arr = np.arange(48)
    # 使用 pytest 的断言来验证是否抛出预期异常,并匹配异常消息
    with pytest.raises(ValueError, match=msg):
        arr.mT


# 定义测试函数,验证二维数组的转置操作
def test_matrix_transpose_equals_transpose_2d():
    arr = np.arange(48).reshape((6, 8))
    # 使用 assert_array_equal 函数验证 arr.T 是否等于 arr.mT
    assert_array_equal(arr.T, arr.mT)


# 定义多个数组形状用于参数化测试
ARRAY_SHAPES_TO_TEST = (
    (5, 2),
    (5, 2, 3),
    (5, 2, 3, 4),
)


# 参数化测试函数,验证 swapaxes 函数的结果与自定义转置操作 mT 相等
@pytest.mark.parametrize("shape", ARRAY_SHAPES_TO_TEST)
def test_matrix_transpose_equals_swapaxes(shape):
    num_of_axes = len(shape)
    vec = np.arange(shape[-1])
    arr = np.broadcast_to(vec, shape)
    tgt = np.swapaxes(arr, num_of_axes - 2, num_of_axes - 1)
    mT = arr.mT  # 执行自定义转置操作 mT
    # 使用 assert_array_equal 函数验证 tgt 是否等于 mT
    assert_array_equal(tgt, mT)

.\numpy\numpy\_core\tests\test_arrayprint.py

# 导入必要的模块和库
import sys  # 导入系统相关的功能模块
import gc  # 导入垃圾回收模块
from hypothesis import given  # 从假设测试框架导入给定装饰器
from hypothesis.extra import numpy as hynp  # 导入假设测试框架的NumPy扩展
import pytest  # 导入 pytest 测试框架

import numpy as np  # 导入 NumPy 库
from numpy.testing import (  # 导入 NumPy 测试工具
    assert_, assert_equal, assert_raises, assert_warns, HAS_REFCOUNT,
    assert_raises_regex,
    )
from numpy._core.arrayprint import _typelessdata  # 导入 NumPy 数组打印相关功能
import textwrap  # 导入文本包装模块

class TestArrayRepr:
    def test_nan_inf(self):
        # 创建包含 NaN 和 Inf 的 NumPy 数组
        x = np.array([np.nan, np.inf])
        assert_equal(repr(x), 'array([nan, inf])')  # 断言数组的 repr 字符串

    def test_subclass(self):
        # 定义一个继承自 np.ndarray 的子类
        class sub(np.ndarray): pass

        # 一维数组示例
        x1d = np.array([1, 2]).view(sub)
        assert_equal(repr(x1d), 'sub([1, 2])')  # 断言子类数组的 repr 字符串

        # 二维数组示例
        x2d = np.array([[1, 2], [3, 4]]).view(sub)
        assert_equal(repr(x2d),
            'sub([[1, 2],\n'
            '     [3, 4]])')  # 断言子类二维数组的 repr 字符串

        # 带有灵活数据类型的二维数组示例
        xstruct = np.ones((2,2), dtype=[('a', '<i4')]).view(sub)
        assert_equal(repr(xstruct),
            "sub([[(1,), (1,)],\n"
            "     [(1,), (1,)]]"  # 断言带有结构化数据类型的子类数组的 repr 字符串
            ", dtype=[('a', '<i4')])"
        )

    @pytest.mark.xfail(reason="See gh-10544")  # 标记此测试用例为预期失败的情况
    def test_object_subclass(self):
        # 定义一个继承自 np.ndarray 的对象子类
        class sub(np.ndarray):
            def __new__(cls, inp):
                obj = np.asarray(inp).view(cls)
                return obj

            def __getitem__(self, ind):
                ret = super().__getitem__(ind)
                return sub(ret)

        # 测试对象 + 子类是否正常工作
        x = sub([None, None])
        assert_equal(repr(x), 'sub([None, None], dtype=object)')  # 断言对象子类的 repr 字符串
        assert_equal(str(x), '[None None]')  # 断言对象子类的字符串表示

        x = sub([None, sub([None, None])])
        assert_equal(repr(x),
            'sub([None, sub([None, None], dtype=object)], dtype=object)')  # 断言嵌套对象子类的 repr 字符串
        assert_equal(str(x), '[None sub([None, None], dtype=object)]')  # 断言嵌套对象子类的字符串表示
    def test_0d_object_subclass(self):
        # 确保返回 0ds 而不是标量的子类不会在 str 方法中引起无限递归

        class sub(np.ndarray):
            def __new__(cls, inp):
                # 将输入转换为 ndarray 并视图化为当前类的对象
                obj = np.asarray(inp).view(cls)
                return obj

            def __getitem__(self, ind):
                # 调用父类的 __getitem__ 方法获取索引处的值
                ret = super().__getitem__(ind)
                # 将获取的值转换为当前类的对象并返回
                return sub(ret)

        x = sub(1)
        assert_equal(repr(x), 'sub(1)')
        assert_equal(str(x), '1')

        x = sub([1, 1])
        assert_equal(repr(x), 'sub([1, 1])')
        assert_equal(str(x), '[1 1]')

        # 检查它在对象数组中的使用是否正常工作
        x = sub(None)
        assert_equal(repr(x), 'sub(None, dtype=object)')
        assert_equal(str(x), 'None')

        # 测试递归的对象数组(即使深度 > 1)
        y = sub(None)
        x[()] = y
        y[()] = x
        assert_equal(repr(x),
            'sub(sub(sub(..., dtype=object), dtype=object), dtype=object)')
        assert_equal(str(x), '...')
        x[()] = 0  # 解决循环引用以便垃圾收集器处理

        # 嵌套的 0d 子类对象
        x = sub(None)
        x[()] = sub(None)
        assert_equal(repr(x), 'sub(sub(None, dtype=object), dtype=object)')
        assert_equal(str(x), 'None')

        # gh-10663
        class DuckCounter(np.ndarray):
            def __getitem__(self, item):
                result = super().__getitem__(item)
                if not isinstance(result, DuckCounter):
                    result = result[...].view(DuckCounter)
                return result

            def to_string(self):
                return {0: 'zero', 1: 'one', 2: 'two'}.get(self.item(), 'many')

            def __str__(self):
                if self.shape == ():
                    return self.to_string()
                else:
                    fmt = {'all': lambda x: x.to_string()}
                    return np.array2string(self, formatter=fmt)

        dc = np.arange(5).view(DuckCounter)
        assert_equal(str(dc), "[zero one two many many]")
        assert_equal(str(dc[0]), "zero")

    def test_self_containing(self):
        # 测试包含自身引用的情况

        arr0d = np.array(None)
        arr0d[()] = arr0d
        assert_equal(repr(arr0d),
            'array(array(..., dtype=object), dtype=object)')
        arr0d[()] = 0  # 解决循环引用以便垃圾收集器处理

        arr1d = np.array([None, None])
        arr1d[1] = arr1d
        assert_equal(repr(arr1d),
            'array([None, array(..., dtype=object)], dtype=object)')
        arr1d[1] = 0  # 解决循环引用以便垃圾收集器处理

        first = np.array(None)
        second = np.array(None)
        first[()] = second
        second[()] = first
        assert_equal(repr(first),
            'array(array(array(..., dtype=object), dtype=object), dtype=object)')
        first[()] = 0  # 解决循环引用以便垃圾收集器处理
    # 定义测试方法,测试包含列表的情况

        # 创建一个包含两个元素的一维 NumPy 数组,初始值为 None
        arr1d = np.array([None, None])

        # 在数组的第一个位置插入一个包含两个元素的列表 [1, 2]
        arr1d[0] = [1, 2]

        # 在数组的第二个位置插入一个包含一个元素的列表 [3]
        arr1d[1] = [3]

        # 断言数组的字符串表示,确认包含了预期的列表结构
        assert_equal(repr(arr1d),
            'array([list([1, 2]), list([3])], dtype=object)')

    # 定义测试方法,测试空标量递归的情况

        # 运行 repr(np.void(b'test')),测试是否会出现递归错误
        repr(np.void(b'test'))  # RecursionError ?

    # 定义测试方法,测试没有字段的结构化数组情况

        # 创建一个没有字段的数据类型对象
        no_fields = np.dtype([])

        # 创建一个包含 4 个元素的空数组,使用上面定义的无字段数据类型
        arr_no_fields = np.empty(4, dtype=no_fields)

        # 断言数组的字符串表示,确认数组中每个元素都是空元组
        assert_equal(repr(arr_no_fields), 'array([(), (), (), ()], dtype=[])')
class TestComplexArray:
    def test_str(self):
        # 定义实数和复数的测试值列表,包括整数、无穷大和NaN
        rvals = [0, 1, -1, np.inf, -np.inf, np.nan]
        # 生成复数的列表,包括所有可能的实部和虚部组合
        cvals = [complex(rp, ip) for rp in rvals for ip in rvals]
        # 定义测试的复数数据类型列表
        dtypes = [np.complex64, np.cdouble, np.clongdouble]
        # 生成实际结果的列表,包括每个复数在每种数据类型下的字符串表示
        actual = [str(np.array([c], dt)) for c in cvals for dt in dtypes]
        # 期望的结果列表,包含每个复数在每种数据类型下的预期字符串表示
        wanted = [
            '[0.+0.j]',    '[0.+0.j]',    '[0.+0.j]',
            '[0.+1.j]',    '[0.+1.j]',    '[0.+1.j]',
            '[0.-1.j]',    '[0.-1.j]',    '[0.-1.j]',
            '[0.+infj]',   '[0.+infj]',   '[0.+infj]',
            '[0.-infj]',   '[0.-infj]',   '[0.-infj]',
            '[0.+nanj]',   '[0.+nanj]',   '[0.+nanj]',
            '[1.+0.j]',    '[1.+0.j]',    '[1.+0.j]',
            '[1.+1.j]',    '[1.+1.j]',    '[1.+1.j]',
            '[1.-1.j]',    '[1.-1.j]',    '[1.-1.j]',
            '[1.+infj]',   '[1.+infj]',   '[1.+infj]',
            '[1.-infj]',   '[1.-infj]',   '[1.-infj]',
            '[1.+nanj]',   '[1.+nanj]',   '[1.+nanj]',
            '[-1.+0.j]',   '[-1.+0.j]',   '[-1.+0.j]',
            '[-1.+1.j]',   '[-1.+1.j]',   '[-1.+1.j]',
            '[-1.-1.j]',   '[-1.-1.j]',   '[-1.-1.j]',
            '[-1.+infj]',  '[-1.+infj]',  '[-1.+infj]',
            '[-1.-infj]',  '[-1.-infj]',  '[-1.-infj]',
            '[-1.+nanj]',  '[-1.+nanj]',  '[-1.+nanj]',
            '[inf+0.j]',   '[inf+0.j]',   '[inf+0.j]',
            '[inf+1.j]',   '[inf+1.j]',   '[inf+1.j]',
            '[inf-1.j]',   '[inf-1.j]',   '[inf-1.j]',
            '[inf+infj]',  '[inf+infj]',  '[inf+infj]',
            '[inf-infj]',  '[inf-infj]',  '[inf-infj]',
            '[inf+nanj]',  '[inf+nanj]',  '[inf+nanj]',
            '[-inf+0.j]',  '[-inf+0.j]',  '[-inf+0.j]',
            '[-inf+1.j]',  '[-inf+1.j]',  '[-inf+1.j]',
            '[-inf-1.j]',  '[-inf-1.j]',  '[-inf-1.j]',
            '[-inf+infj]', '[-inf+infj]', '[-inf+infj]',
            '[-inf-infj]', '[-inf-infj]', '[-inf-infj]',
            '[-inf+nanj]', '[-inf+nanj]', '[-inf+nanj]',
            '[nan+0.j]',   '[nan+0.j]',   '[nan+0.j]',
            '[nan+1.j]',   '[nan+1.j]',   '[nan+1.j]',
            '[nan-1.j]',   '[nan-1.j]',   '[nan-1.j]',
            '[nan+infj]',  '[nan+infj]',  '[nan+infj]',
            '[nan-infj]',  '[nan-infj]',  '[nan-infj]',
            '[nan+nanj]',  '[nan+nanj]',  '[nan+nanj]']

        # 对每个实际结果和期望结果进行断言比较
        for res, val in zip(actual, wanted):
            assert_equal(res, val)

class TestArray2String:
    def test_basic(self):
        """Basic test of array2string."""
        # 创建一个简单的整数数组
        a = np.arange(3)
        # 断言默认设置下整数数组的字符串表示
        assert_(np.array2string(a) == '[0 1 2]')
        # 断言在特定设置下整数数组的字符串表示,包括最大行宽和遗留模式
        assert_(np.array2string(a, max_line_width=4, legacy='1.13') == '[0 1\n 2]')
        # 断言在特定设置下整数数组的字符串表示,包括最大行宽
        assert_(np.array2string(a, max_line_width=4) == '[0\n 1\n 2]')
    # 定义测试函数:验证当传递给 array2string 函数一个未预期的关键字参数时,是否引发适当的 TypeError 异常
    def test_unexpected_kwarg(self):
        # 使用 assert_raises_regex 上下文管理器断言捕获的异常为 TypeError,并且异常消息中包含 'nonsense'
        with assert_raises_regex(TypeError, 'nonsense'):
            # 调用 np.array2string 函数,传递一个数组和一个未预期的关键字参数 nonsense=None
            np.array2string(np.array([1, 2, 3]),
                            nonsense=None)

    # 定义测试函数:测试自定义的格式化函数用于数组中每个元素
    def test_format_function(self):
        """Test custom format function for each element in array."""
        
        # 定义内部函数 _format_function,根据元素的绝对值选择不同的字符表示
        def _format_function(x):
            if np.abs(x) < 1:
                return '.'
            elif np.abs(x) < 2:
                return 'o'
            else:
                return 'O'

        # 创建一个包含 [0, 1, 2] 的整数数组 x
        x = np.arange(3)
        # 创建预期的十六进制字符串表示
        x_hex = "[0x0 0x1 0x2]"
        # 创建预期的八进制字符串表示
        x_oct = "[0o0 0o1 0o2]"
        
        # 使用 assert_ 断言 np.array2string 函数的结果符合预期
        assert_(np.array2string(x, formatter={'all':_format_function}) ==
                "[. o O]")
        assert_(np.array2string(x, formatter={'int_kind':_format_function}) ==
                "[. o O]")
        assert_(np.array2string(x, formatter={'all':lambda x: "%.4f" % x}) ==
                "[0.0000 1.0000 2.0000]")
        
        # 使用 assert_equal 断言 np.array2string 函数的结果与预期的十六进制字符串相等
        assert_equal(np.array2string(x, formatter={'int':lambda x: hex(x)}),
                     x_hex)
        # 使用 assert_equal 断言 np.array2string 函数的结果与预期的八进制字符串相等
        assert_equal(np.array2string(x, formatter={'int':lambda x: oct(x)}),
                     x_oct)

        # 创建一个包含 [0. 1. 2.] 的浮点数数组 x
        x = np.arange(3.)
        # 使用 assert_ 断言 np.array2string 函数的结果符合预期的浮点数格式
        assert_(np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x}) ==
                "[0.00 1.00 2.00]")
        assert_(np.array2string(x, formatter={'float':lambda x: "%.2f" % x}) ==
                "[0.00 1.00 2.00]")

        # 创建一个包含 ['abc', 'def'] 的字符串数组 s
        s = np.array(['abc', 'def'])
        # 使用 assert_ 断言 np.array2string 函数的结果符合预期的字符串加倍格式
        assert_(np.array2string(s, formatter={'numpystr':lambda s: s*2}) ==
                '[abcabc defdef]')
    def test_structure_format_mixed(self):
        # 定义结构化数据类型 dt,包含字段 'name' 和 'grades'
        dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
        
        # 创建一个结构化数组 x,包含两个条目:('Sarah', [8.0, 7.0]) 和 ('John', [6.0, 7.0])
        x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
        
        # 使用 assert_equal 函数验证 np.array2string(x) 的输出是否符合预期
        assert_equal(np.array2string(x),
                "[('Sarah', [8., 7.]) ('John', [6., 7.])]")

        # 设置打印选项,使用 'legacy' 模式为 '1.13'
        np.set_printoptions(legacy='1.13')
        try:
            # 创建一个包含 'A' 字段的零填充数组 A,数据类型为 "M8[s]"
            A = np.zeros(shape=10, dtype=[("A", "M8[s]")])
            
            # 将数组 A 的从索引 5 开始的元素填充为 NaT (Not a Time)
            A[5:].fill(np.datetime64('NaT'))
            
            # 使用 assert_equal 函数验证 np.array2string(A) 的输出是否符合预期
            assert_equal(
                np.array2string(A),
                textwrap.dedent("""\
                [('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',)
                 ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('NaT',) ('NaT',)
                 ('NaT',) ('NaT',) ('NaT',)]""")
            )
        finally:
            # 恢复非 legacy 打印选项
            np.set_printoptions(legacy=False)

        # 再次验证非 legacy 模式下的输出
        assert_equal(
            np.array2string(A),
            textwrap.dedent("""\
            [('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',)
             ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',)
             ('1970-01-01T00:00:00',) (                'NaT',)
             (                'NaT',) (                'NaT',)
             (                'NaT',) (                'NaT',)]""")
        )

        # 使用 timedeltas 的情况再次验证输出
        A = np.full(10, 123456, dtype=[("A", "m8[s]")])
        A[5:].fill(np.datetime64('NaT'))
        assert_equal(
            np.array2string(A),
            textwrap.dedent("""\
            [(123456,) (123456,) (123456,) (123456,) (123456,) ( 'NaT',) ( 'NaT',)
             ( 'NaT',) ( 'NaT',) ( 'NaT',)]""")
        )

    def test_structure_format_int(self):
        # See #8160
        # 创建一个包含整数数组的结构化数组 struct_int
        struct_int = np.array([([1, -1],), ([123, 1],)],
                dtype=[('B', 'i4', 2)])
        
        # 使用 assert_equal 函数验证 np.array2string(struct_int) 的输出是否符合预期
        assert_equal(np.array2string(struct_int),
                "[([  1,  -1],) ([123,   1],)]")
        
        # 创建一个包含二维整数数组的结构化数组 struct_2dint
        struct_2dint = np.array([([[0, 1], [2, 3]],), ([[12, 0], [0, 0]],)],
                dtype=[('B', 'i4', (2, 2))])
        
        # 使用 assert_equal 函数验证 np.array2string(struct_2dint) 的输出是否符合预期
        assert_equal(np.array2string(struct_2dint),
                "[([[ 0,  1], [ 2,  3]],) ([[12,  0], [ 0,  0]],)]")

    def test_structure_format_float(self):
        # See #8172
        # 创建一个包含浮点数的数组 array_scalar
        array_scalar = np.array(
                (1., 2.1234567890123456789, 3.), dtype=('f8,f8,f8'))
        
        # 使用 assert_equal 函数验证 np.array2string(array_scalar) 的输出是否符合预期
        assert_equal(np.array2string(array_scalar), "(1., 2.12345679, 3.)")
    # 测试 void 类型数组的表示形式
    def test_unstructured_void_repr(self):
        # 创建一个 numpy 数组,使用 'u1' 类型,视图类型为 'V8',包含特定的字节序列
        a = np.array([27, 91, 50, 75,  7, 65, 10,  8,
                      27, 91, 51, 49,109, 82,101,100], dtype='u1').view('V8')
        # 断言第一个数组元素的 repr 结果
        assert_equal(repr(a[0]),
            r"np.void(b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08')")
        # 断言第一个数组元素的 str 结果
        assert_equal(str(a[0]), r"b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08'")
        # 断言整个数组的 repr 结果
        assert_equal(repr(a),
            r"array([b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08'," "\n"
            r"       b'\x1B\x5B\x33\x31\x6D\x52\x65\x64'], dtype='|V8')")

        # 使用 eval 函数检查 repr(a) 的结果是否与原始数组 a 相等
        assert_equal(eval(repr(a), vars(np)), a)
        # 使用 eval 函数检查 repr(a[0]) 的结果是否与原始数组 a[0] 相等
        assert_equal(eval(repr(a[0]), dict(np=np)), a[0])

    # 测试 np.array2string 函数的 edgeitems 关键字参数
    def test_edgeitems_kwarg(self):
        # 创建一个包含三个整数零的数组
        arr = np.zeros(3, int)
        # 断言 np.array2string 函数对数组 arr 使用 edgeitems=1, threshold=0 的结果
        assert_equal(
            np.array2string(arr, edgeitems=1, threshold=0),
            "[0 ... 0]"
        )

    # 测试 1 维数组的 summarize 功能
    def test_summarize_1d(self):
        # 创建一个包含 0 到 1000 的整数的数组
        A = np.arange(1001)
        # 期望的字符串表示
        strA = '[   0    1    2 ...  998  999 1000]'
        # 断言数组 A 的字符串表示是否符合预期
        assert_equal(str(A), strA)

        # 期望的 repr 表示
        reprA = 'array([   0,    1,    2, ...,  998,  999, 1000])'
        # 断言数组 A 的 repr 表示是否符合预期
        assert_equal(repr(A), reprA)

    # 测试 2 维数组的 summarize 功能
    def test_summarize_2d(self):
        # 创建一个包含 0 到 1001 的整数,形状为 (2, 501) 的数组
        A = np.arange(1002).reshape(2, 501)
        # 期望的字符串表示
        strA = '[[   0    1    2 ...  498  499  500]\n' \
               ' [ 501  502  503 ...  999 1000 1001]]'
        # 断言数组 A 的字符串表示是否符合预期
        assert_equal(str(A), strA)

        # 期望的 repr 表示
        reprA = 'array([[   0,    1,    2, ...,  498,  499,  500],\n' \
                '       [ 501,  502,  503, ...,  999, 1000, 1001]])'
        # 断言数组 A 的 repr 表示是否符合预期
        assert_equal(repr(A), reprA)

    # 测试结构化数组的 summarize 功能
    def test_summarize_structure(self):
        # 创建一个结构化数组 A,包含两个字段,每个字段是包含 0 到 1000 的整数的数组
        A = (np.arange(2002, dtype="<i8").reshape(2, 1001)
             .view([('i', "<i8", (1001,))]))
        # 期望的字符串表示
        strA = ("[[([   0,    1,    2, ...,  998,  999, 1000],)]\n"
                " [([1001, 1002, 1003, ..., 1999, 2000, 2001],)]]")
        # 断言数组 A 的字符串表示是否符合预期
        assert_equal(str(A), strA)

        # 期望的 repr 表示
        reprA = ("array([[([   0,    1,    2, ...,  998,  999, 1000],)],\n"
                 "       [([1001, 1002, 1003, ..., 1999, 2000, 2001],)]],\n"
                 "      dtype=[('i', '<i8', (1001,))])")
        # 断言数组 A 的 repr 表示是否符合预期
        assert_equal(repr(A), reprA)

        # 创建一个结构化数组 B,包含一个字段,每个字段是包含 1 的数组
        B = np.ones(2002, dtype=">i8").view([('i', ">i8", (2, 1001))])
        # 期望的字符串表示
        strB = "[([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)]"
        # 断言数组 B 的字符串表示是否符合预期
        assert_equal(str(B), strB)

        # 期望的 repr 表示
        reprB = (
            "array([([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)],\n"
            "      dtype=[('i', '>i8', (2, 1001))])"
        )
        # 断言数组 B 的 repr 表示是否符合预期
        assert_equal(repr(B), reprB)

        # 创建一个结构化数组 C,包含两个字段,每个字段是包含 0 到 21 的整数的数组
        C = (np.arange(22, dtype="<i8").reshape(2, 11)
             .view([('i1', "<i8"), ('i10', "<i8", (10,))]))
        # 期望的字符串表示
        strC = "[[( 0, [ 1, ..., 10])]\n [(11, [12, ..., 21])]]"
        # 使用 np.array2string 函数,并设置 threshold=1, edgeitems=1
        # 断言数组 C 的字符串表示是否符合预期
        assert_equal(np.array2string(C, threshold=1, edgeitems=1), strC)
    # 定义测试方法,用于测试数组转换为字符串时的行宽限制
    def test_linewidth(self):
        # 创建一个包含六个元素的全1数组
        a = np.full(6, 1)

        # 定义内部函数make_str,将数组转换为字符串,控制最大行宽
        def make_str(a, width, **kw):
            return np.array2string(a, separator="", max_line_width=width, **kw)

        # 断言不同行宽下的字符串转换结果
        assert_equal(make_str(a, 8, legacy='1.13'), '[111111]')
        assert_equal(make_str(a, 7, legacy='1.13'), '[111111]')
        assert_equal(make_str(a, 5, legacy='1.13'), '[1111\n'
                                                    ' 11]')

        assert_equal(make_str(a, 8), '[111111]')
        assert_equal(make_str(a, 7), '[11111\n'
                                     ' 1]')
        assert_equal(make_str(a, 5), '[111\n'
                                     ' 111]')

        # 将a数组转换为形状为(1, 1, 6)的数组b
        b = a[None,None,:]

        # 断言不同行宽下的多维数组转换结果
        assert_equal(make_str(b, 12, legacy='1.13'), '[[[111111]]]')
        assert_equal(make_str(b,  9, legacy='1.13'), '[[[111111]]]')
        assert_equal(make_str(b,  8, legacy='1.13'), '[[[11111\n'
                                                     '   1]]]')

        assert_equal(make_str(b, 12), '[[[111111]]]')
        assert_equal(make_str(b,  9), '[[[111\n'
                                      '   111]]]')
        assert_equal(make_str(b,  8), '[[[11\n'
                                      '   11\n'
                                      '   11]]]')

    # 定义测试方法,用于测试数组中包含宽元素时的转换为字符串操作
    def test_wide_element(self):
        # 创建包含单个字符串元素的数组a
        a = np.array(['xxxxx'])
        
        # 断言在限制最大行宽为5时的数组转换结果
        assert_equal(
            np.array2string(a, max_line_width=5),
            "['xxxxx']"
        )
        
        # 断言在限制最大行宽为5且使用旧版本模式时的数组转换结果
        assert_equal(
            np.array2string(a, max_line_width=5, legacy='1.13'),
            "[ 'xxxxx']"
        )
    def test_multiline_repr(self):
        # 定义一个具有多行字符串表示的类 MultiLine
        class MultiLine:
            # 定义该类的 __repr__ 方法,返回多行字符串
            def __repr__(self):
                return "Line 1\nLine 2"

        # 创建一个包含 MultiLine 对象的 NumPy 数组 a
        a = np.array([[None, MultiLine()], [MultiLine(), None]])

        # 断言调用 np.array2string 函数后的返回结果
        assert_equal(
            np.array2string(a),
            '[[None Line 1\n'
            '       Line 2]\n'
            ' [Line 1\n'
            '  Line 2 None]]'
        )

        # 断言调用 np.array2string 函数(限定最大行宽为 5)后的返回结果
        assert_equal(
            np.array2string(a, max_line_width=5),
            '[[None\n'
            '  Line 1\n'
            '  Line 2]\n'
            ' [Line 1\n'
            '  Line 2\n'
            '  None]]'
        )

        # 断言调用 repr 函数后的返回结果
        assert_equal(
            repr(a),
            'array([[None, Line 1\n'
            '              Line 2],\n'
            '       [Line 1\n'
            '        Line 2, None]], dtype=object)'
        )

        # 定义一个更长的多行字符串表示的类 MultiLineLong
        class MultiLineLong:
            # 定义该类的 __repr__ 方法,返回更长的多行字符串
            def __repr__(self):
                return "Line 1\nLooooooooooongestLine2\nLongerLine 3"

        # 创建一个包含 MultiLineLong 对象的 NumPy 数组 a
        a = np.array([[None, MultiLineLong()], [MultiLineLong(), None]])

        # 断言调用 repr 函数后的返回结果
        assert_equal(
            repr(a),
            'array([[None, Line 1\n'
            '              LooooooooooongestLine2\n'
            '              LongerLine 3          ],\n'
            '       [Line 1\n'
            '        LooooooooooongestLine2\n'
            '        LongerLine 3          , None]], dtype=object)'
        )

        # 断言调用 np.array_repr 函数(限定每行最大字符数为 20)后的返回结果
        assert_equal(
            np.array_repr(a, 20),
            'array([[None,\n'
            '        Line 1\n'
            '        LooooooooooongestLine2\n'
            '        LongerLine 3          ],\n'
            '       [Line 1\n'
            '        LooooooooooongestLine2\n'
            '        LongerLine 3          ,\n'
            '        None]],\n'
            '      dtype=object)'
        )

    def test_nested_array_repr(self):
        # 创建一个空的 NumPy 数组 a,元素类型为对象
        a = np.empty((2, 2), dtype=object)
        # 在数组中填充元素
        a[0, 0] = np.eye(2)
        a[0, 1] = np.eye(3)
        a[1, 0] = None
        a[1, 1] = np.ones((3, 1))

        # 断言调用 repr 函数后的返回结果
        assert_equal(
            repr(a),
            'array([[array([[1., 0.],\n'
            '               [0., 1.]]), array([[1., 0., 0.],\n'
            '                                  [0., 1., 0.],\n'
            '                                  [0., 0., 1.]])],\n'
            '       [None, array([[1.],\n'
            '                     [1.],\n'
            '                     [1.]])]], dtype=object)'
        )

    @given(hynp.from_dtype(np.dtype("U")))
    # 定义一个测试方法,用于检查任意文本的处理
    def test_any_text(self, text):
        # 这个测试检查,对于可以表示为dtype("U")数组的任何值(即Unicode字符串)...
        a = np.array([text, text, text])
        # 将它们的列表转换为数组不会截断值,例如:
        assert_equal(a[0], text)
        # 使用原始的Python字符串来表示下面的repr
        text = text.item()  # 用于下面repr的原始Python字符串
        # 并且确保np.array2string在预期位置放置换行符
        expected_repr = "[{0!r} {0!r}\n {0!r}]".format(text)
        # 调用np.array2string生成结果字符串,限制行宽度为repr(text)长度的两倍加3
        result = np.array2string(a, max_line_width=len(repr(text)) * 2 + 3)
        # 断言生成的结果字符串符合预期的repr格式
        assert_equal(result, expected_repr)

    # 使用pytest的标记,如果没有引用计数,则跳过测试(因为Python缺少引用计数)
    @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
    def test_refcount(self):
        # 确保由于递归闭包(gh-10620),我们不会保留对数组的引用
        gc.disable()
        # 创建一个包含0和1的数组a
        a = np.arange(2)
        # 获取a的引用计数r1
        r1 = sys.getrefcount(a)
        # 调用np.array2string(a),不应该增加对a的引用计数
        np.array2string(a)
        np.array2string(a)
        # 再次获取a的引用计数r2
        r2 = sys.getrefcount(a)
        gc.collect()  # 手动垃圾回收
        gc.enable()
        # 断言在禁用和启用gc之间,a的引用计数没有变化
        assert_(r1 == r2)
    # 定义一个测试方法,用于测试带有符号输出的功能
    def test_with_sign(self):
        # 创建一个包含负数和正数值的 NumPy 数组
        a = np.array([-2, 0, 3])
        # 断言使用 '+' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='+'),
            '[-2 +0 +3]'
        )
        # 断言使用 '-' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='-'),
            '[-2  0  3]'
        )
        # 断言使用空格符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign=' '),
            '[-2  0  3]'
        )
        # 创建一个全部为非负数的 NumPy 数组
        a = np.array([2, 0, 3])
        # 断言使用 '+' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='+'),
            '[+2 +0 +3]'
        )
        # 断言使用 '-' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='-'),
            '[2 0 3]'
        )
        # 断言使用空格符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign=' '),
            '[ 2  0  3]'
        )
        # 创建一个全部为负数的 NumPy 数组
        a = np.array([-2, -1, -3])
        # 断言使用 '+' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='+'),
            '[-2 -1 -3]'
        )
        # 断言使用 '-' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='-'),
            '[-2 -1 -3]'
        )
        # 断言使用空格符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign=' '),
            '[-2 -1 -3]'
        )
        # 创建一个二维数组,混合负数和正数
        a = np.array([[10, -1, 1, 1], [10, 10, 10, 10]])
        # 断言使用 '+' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='+'),
            '[[+10  -1  +1  +1]\n [+10 +10 +10 +10]]'
        )
        # 断言使用 '-' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='-'),
            '[[10 -1  1  1]\n [10 10 10 10]]'
        )
        # 断言使用空格符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign=' '),
            '[[10 -1  1  1]\n [10 10 10 10]]'
        )
        # 创建一个二维数组,全部为正数
        a = np.array([[10, 0, 1, 1], [10, 10, 10, 10]])
        # 断言使用 '+' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='+'),
            '[[+10  +0  +1  +1]\n [+10 +10 +10 +10]]'
        )
        # 断言使用 '-' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='-'),
            '[[10  0  1  1]\n [10 10 10 10]]'
        )
        # 断言使用空格符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign=' '),
            '[[ 10   0   1   1]\n [ 10  10  10  10]]'
        )
        # 创建一个二维数组,全部为负数
        a = np.array([[-10, -1, -1, -1], [-10, -10, -10, -10]])
        # 断言使用 '+' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='+'),
            '[[-10  -1  -1  -1]\n [-10 -10 -10 -10]]'
        )
        # 断言使用 '-' 符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign='-'),
            '[[-10  -1  -1  -1]\n [-10 -10 -10 -10]]'
        )
        # 断言使用空格符号输出数组的字符串表示
        assert_equal(
            np.array2string(a, sign=' '),
            '[[-10  -1  -1  -1]\n [-10 -10 -10 -10]]'
        )
# 定义一个测试类 TestPrintOptions,用于测试获取和设置全局打印选项
class TestPrintOptions:
    """Test getting and setting global print options."""

    # 设置每个测试方法的初始化方法
    def setup_method(self):
        # 获取当前的打印选项并保存为旧选项
        self.oldopts = np.get_printoptions()

    # 设置每个测试方法的清理方法
    def teardown_method(self):
        # 恢复之前保存的旧打印选项
        np.set_printoptions(**self.oldopts)

    # 测试基本的打印精度设置
    def test_basic(self):
        # 创建一个包含浮点数的 NumPy 数组
        x = np.array([1.5, 0, 1.234567890])
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([1.5       , 0.        , 1.23456789])")
        # 设置新的打印选项,修改精度为 4
        np.set_printoptions(precision=4)
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([1.5   , 0.    , 1.2346])")

    # 测试精度设置为零时的打印输出
    def test_precision_zero(self):
        # 设置打印选项,精度设为 0
        np.set_printoptions(precision=0)
        # 迭代测试不同值和对应的字符串表示
        for values, string in (
                ([0.], "0."), ([.3], "0."), ([-.3], "-0."), ([.7], "1."),
                ([1.5], "2."), ([-1.5], "-2."), ([-15.34], "-15."),
                ([100.], "100."), ([.2, -1, 122.51], "  0.,  -1., 123."),
                ([0], "0"), ([-12], "-12"), ([complex(.3, -.7)], "0.-1.j")):
            # 创建包含特定值的 NumPy 数组
            x = np.array(values)
            # 断言数组的字符串表示与期望相符
            assert_equal(repr(x), "array([%s])" % string)

    # 测试自定义格式化函数的打印输出
    def test_formatter(self):
        # 创建一个整数范围的 NumPy 数组
        x = np.arange(3)
        # 设置自定义格式化函数,将所有元素减一后转为字符串
        np.set_printoptions(formatter={'all': lambda x: str(x - 1)})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([-1, 0, 1])")

    # 测试重置格式化函数后的打印输出
    def test_formatter_reset(self):
        # 创建一个整数范围的 NumPy 数组
        x = np.arange(3)
        # 设置自定义格式化函数,将所有元素减一后转为字符串
        np.set_printoptions(formatter={'all': lambda x: str(x - 1)})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([-1, 0, 1])")
        # 重置整数格式化函数为默认
        np.set_printoptions(formatter={'int': None})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([0, 1, 2])")

        # 重新设置格式化函数,将所有元素减一后转为字符串
        np.set_printoptions(formatter={'all': lambda x: str(x - 1)})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([-1, 0, 1])")
        # 清除所有格式化函数
        np.set_printoptions(formatter={'all': None})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([0, 1, 2])")

        # 设置整数格式化函数,将所有整数元素减一后转为字符串
        np.set_printoptions(formatter={'int': lambda x: str(x - 1)})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([-1, 0, 1])")
        # 清除整数类型的格式化函数
        np.set_printoptions(formatter={'int_kind': None})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([0, 1, 2])")

        # 创建一个浮点数范围的 NumPy 数组
        x = np.arange(3.)
        # 设置浮点数格式化函数,将所有元素减一后转为字符串
        np.set_printoptions(formatter={'float': lambda x: str(x - 1)})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([-1.0, 0.0, 1.0])")
        # 清除浮点数类型的格式化函数
        np.set_printoptions(formatter={'float_kind': None})
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([0., 1., 2.])")

    # 测试重写 repr 函数后的打印输出
    def test_override_repr(self):
        # 创建一个整数范围的 NumPy 数组
        x = np.arange(3)
        # 设置重写 repr 函数,使其返回固定字符串 "FOO"
        np.set_printoptions(override_repr=lambda x: "FOO")
        # 断言数组的字符串表示为 "FOO"
        assert_equal(repr(x), "FOO")
        # 清除重写的 repr 函数
        np.set_printoptions(override_repr=None)
        # 断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([0, 1, 2])")

        # 使用 with 语句设置重写 repr 函数,使其返回固定字符串 "BAR"
        with np.printoptions(override_repr=lambda x: "BAR"):
            # 断言数组的字符串表示为 "BAR"
            assert_equal(repr(x), "BAR")
        # 离开 with 语句后,断言数组的字符串表示与期望相符
        assert_equal(repr(x), "array([0, 1, 2])")
    def test_0d_arrays(self):
        # 测试对于0维数组的字符串表示,确保将字符串按照指定的格式 '<U4' 进行编码
        assert_equal(str(np.array('café', '<U4')), 'café')

        # 测试对于0维数组的表征,使用repr函数确保返回正确的数组表征字符串
        assert_equal(repr(np.array('café', '<U4')),
                     "array('café', dtype='<U4')")
        
        # 测试对于0维字符串数组的字符串表示
        assert_equal(str(np.array('test', np.str_)), 'test')

        # 创建一个dtype为 [('a', '<i4', (3,))] 的1维零数组,并确保其字符串表示正确
        a = np.zeros(1, dtype=[('a', '<i4', (3,))])
        assert_equal(str(a[0]), '([0, 0, 0],)')

        # 测试对于datetime64类型的0维数组,使用repr确保返回正确的日期字符串
        assert_equal(repr(np.datetime64('2005-02-25')[...]),
                     "array('2005-02-25', dtype='datetime64[D]')")

        # 测试对于timedelta64类型的0维数组,使用repr确保返回正确的时间间隔字符串
        assert_equal(repr(np.timedelta64('10', 'Y')[...]),
                     "array(10, dtype='timedelta64[Y]')")

        # 设置printoptions,测试0维数组的表征受其影响的情况
        x = np.array(1)
        np.set_printoptions(formatter={'all':lambda x: "test"})
        assert_equal(repr(x), "array(test)")
        # str函数不受影响
        assert_equal(str(x), "1")

        # 检查`style`参数引发DeprecationWarning警告
        assert_warns(DeprecationWarning, np.array2string,
                                         np.array(1.), style=repr)
        # 但在legacy模式下不会引发警告
        np.array2string(np.array(1.), style=repr, legacy='1.13')
        # gh-10934:在legacy模式下,style可能不起作用,检查其是否正常工作
        np.array2string(np.array(1.), legacy='1.13')

    def test_float_spacing(self):
        # 创建浮点数数组并检查其字符串表征
        x = np.array([1., 2., 3.])
        y = np.array([1., 2., -10.])
        z = np.array([100., 2., -1.])
        w = np.array([-100., 2., 1.])

        assert_equal(repr(x), 'array([1., 2., 3.])')
        assert_equal(repr(y), 'array([  1.,   2., -10.])')
        assert_equal(repr(np.array(y[0])), 'array(1.)')
        assert_equal(repr(np.array(y[-1])), 'array(-10.)')
        assert_equal(repr(z), 'array([100.,   2.,  -1.])')
        assert_equal(repr(w), 'array([-100.,    2.,    1.])')

        # 检查包含NaN和inf的数组的表征
        assert_equal(repr(np.array([np.nan, np.inf])), 'array([nan, inf])')
        assert_equal(repr(np.array([np.nan, -np.inf])), 'array([ nan, -inf])')

        # 设置精度为2,检查数组表征中浮点数的输出格式
        x = np.array([np.inf, 100000, 1.1234])
        y = np.array([np.inf, 100000, -1.1234])
        z = np.array([np.inf, 1.1234, -1e120])
        np.set_printoptions(precision=2)
        assert_equal(repr(x), 'array([     inf, 1.00e+05, 1.12e+00])')
        assert_equal(repr(y), 'array([      inf,  1.00e+05, -1.12e+00])')
        assert_equal(repr(z), 'array([       inf,  1.12e+000, -1.00e+120])')

    def test_bool_spacing(self):
        # 检查布尔数组的表征,确保正确的空格处理
        assert_equal(repr(np.array([True,  True])),
                     'array([ True,  True])')
        assert_equal(repr(np.array([True, False])),
                     'array([ True, False])')
        assert_equal(repr(np.array([True])),
                     'array([ True])')
        assert_equal(repr(np.array(True)),
                     'array(True)')
        assert_equal(repr(np.array(False)),
                     'array(False)')
    def test_sign_spacing(self):
        # 创建一个包含四个浮点数的数组
        a = np.arange(4.)
        # 创建一个包含单个浮点数的数组
        b = np.array([1.234e9])
        # 创建一个复数数组,指定数据类型为复数
        c = np.array([1.0 + 1.0j, 1.123456789 + 1.123456789j], dtype='c16')

        # 断言:验证数组的字符串表示是否与预期相符
        assert_equal(repr(a), 'array([0., 1., 2., 3.])')
        assert_equal(repr(np.array(1.)), 'array(1.)')
        assert_equal(repr(b), 'array([1.234e+09])')
        assert_equal(repr(np.array([0.])), 'array([0.])')
        assert_equal(repr(c),
            "array([1.        +1.j        , 1.12345679+1.12345679j])")
        assert_equal(repr(np.array([0., -0.])), 'array([ 0., -0.])')

        # 设置 NumPy 打印选项,使符号前面有空格
        np.set_printoptions(sign=' ')
        assert_equal(repr(a), 'array([ 0.,  1.,  2.,  3.])')
        assert_equal(repr(np.array(1.)), 'array( 1.)')
        assert_equal(repr(b), 'array([ 1.234e+09])')
        assert_equal(repr(c),
            "array([ 1.        +1.j        ,  1.12345679+1.12345679j])")
        assert_equal(repr(np.array([0., -0.])), 'array([ 0., -0.])')

        # 设置 NumPy 打印选项,使符号前面为加号
        np.set_printoptions(sign='+')
        assert_equal(repr(a), 'array([+0., +1., +2., +3.])')
        assert_equal(repr(np.array(1.)), 'array(+1.)')
        assert_equal(repr(b), 'array([+1.234e+09])')
        assert_equal(repr(c),
            "array([+1.        +1.j        , +1.12345679+1.12345679j])")

        # 设置 NumPy 打印选项,使用旧版(1.13)的格式
        np.set_printoptions(legacy='1.13')
        assert_equal(repr(a), 'array([ 0.,  1.,  2.,  3.])')
        assert_equal(repr(b),  'array([  1.23400000e+09])')
        assert_equal(repr(-b), 'array([ -1.23400000e+09])')
        assert_equal(repr(np.array(1.)), 'array(1.0)')
        assert_equal(repr(np.array([0.])), 'array([ 0.])')
        assert_equal(repr(c),
            "array([ 1.00000000+1.j        ,  1.12345679+1.12345679j])")
        # gh-10383
        # 断言:验证浮点数数组的字符串表示是否与预期相符
        assert_equal(str(np.array([-1., 10])), "[ -1.  10.]")

        # 断言:检查是否会抛出 TypeError 异常,用于测试 set_printoptions 函数的错误参数
        assert_raises(TypeError, np.set_printoptions, wrongarg=True)

    def test_float_overflow_nowarn(self):
        # 确保 FloatingFormat 内部计算不会警告溢出
        repr(np.array([1e4, 0.1], dtype='f2'))

    def test_sign_spacing_structured(self):
        # 创建一个结构化数组,每个元素包含两个浮点数
        a = np.ones(2, dtype='<f,<f')
        assert_equal(repr(a),
            "array([(1., 1.), (1., 1.)], dtype=[('f0', '<f4'), ('f1', '<f4')])")
        assert_equal(repr(a[0]),
            "np.void((1.0, 1.0), dtype=[('f0', '<f4'), ('f1', '<f4')])")

    def test_legacy_mode_scalars(self):
        # 在旧版模式下,浮点数的字符串表示被截断,复数标量使用 * 表示非有限虚部
        np.set_printoptions(legacy='1.13')
        assert_equal(str(np.float64(1.123456789123456789)), '1.12345678912')
        assert_equal(str(np.complex128(complex(1, np.nan))), '(1+nan*j)')

        # 关闭旧版模式
        np.set_printoptions(legacy=False)
        assert_equal(str(np.float64(1.123456789123456789)),
                     '1.1234567891234568')
        assert_equal(str(np.complex128(complex(1, np.nan))), '(1+nanj)')
    @pytest.mark.parametrize(
        ['native'],
        [
            ('bool',),
            ('uint8',),
            ('uint16',),
            ('uint32',),
            ('uint64',),
            ('int8',),
            ('int16',),
            ('int32',),
            ('int64',),
            ('float16',),
            ('float32',),
            ('float64',),
            ('U1',),     # 4-byte width string
        ],
    )
    def test_dtype_endianness_repr(self, native):
        '''
        there was an issue where
        repr(array([0], dtype='<u2')) and repr(array([0], dtype='>u2'))
        both returned the same thing:
        array([0], dtype=uint16)
        even though their dtypes have different endianness.
        '''
        # 将参数化测试用例标记为'test_dtype_endianness_repr',传入单个参数'native',其取值范围为以下类型
        native_dtype = np.dtype(native)
        # 使用参数'native'构建NumPy数据类型对象
        non_native_dtype = native_dtype.newbyteorder()
        # 获取'native_dtype'的非本地字节顺序版本的数据类型对象
        non_native_repr = repr(np.array([1], non_native_dtype))
        # 获取包含非本地字节顺序的数组的字符串表示形式
        native_repr = repr(np.array([1], native_dtype))
        # 获取包含本地字节顺序的数组的字符串表示形式
        # 保持默认的合理性,只在类型非标准时显示数据类型
        assert ('dtype' in native_repr) ^ (native_dtype in _typelessdata),\
                ("an array's repr should show dtype if and only if the type "
                 'of the array is NOT one of the standard types '
                 '(e.g., int32, bool, float64).')
        # 断言:如果非本地字节顺序的数据类型的项大小大于1字节,则其表示形式与本地字节顺序的表示形式不同
        if non_native_dtype.itemsize > 1:
            # 如果数据类型的大小大于1字节,则非本地字节顺序版本必须显示字节顺序
            assert non_native_repr != native_repr
            assert f"dtype='{non_native_dtype.byteorder}" in non_native_repr
    def test_linewidth_repr(self):
        # 创建一个长度为7的NumPy数组,每个元素填充为2
        a = np.full(7, fill_value=2)
        # 设置打印选项,限制每行字符数为17
        np.set_printoptions(linewidth=17)
        # 断言数组的字符串表示是否与指定的格式化字符串相等
        assert_equal(
            repr(a),
            textwrap.dedent("""\
            array([2, 2, 2,
                   2, 2, 2,
                   2])""")
        )
        # 修改打印选项,保持限制每行字符数为17,使用1.13版的遗留模式
        np.set_printoptions(linewidth=17, legacy='1.13')
        # 再次断言数组的字符串表示是否符合新的格式化字符串
        assert_equal(
            repr(a),
            textwrap.dedent("""\
            array([2, 2, 2,
                   2, 2, 2, 2])""")
        )

        # 创建一个长度为8的NumPy数组,每个元素填充为2
        a = np.full(8, fill_value=2)

        # 修改打印选项,限制每行字符数为18,不使用遗留模式
        np.set_printoptions(linewidth=18, legacy=False)
        # 断言数组的字符串表示是否与指定的格式化字符串相等
        assert_equal(
            repr(a),
            textwrap.dedent("""\
            array([2, 2, 2,
                   2, 2, 2,
                   2, 2])""")
        )

        # 修改打印选项,限制每行字符数为18,使用1.13版的遗留模式
        np.set_printoptions(linewidth=18, legacy='1.13')
        # 再次断言数组的字符串表示是否符合新的格式化字符串
        assert_equal(
            repr(a),
            textwrap.dedent("""\
            array([2, 2, 2, 2,
                   2, 2, 2, 2])""")
        )

    def test_linewidth_str(self):
        # 创建一个长度为18的NumPy数组,每个元素填充为2
        a = np.full(18, fill_value=2)
        # 设置打印选项,限制每行字符数为18
        np.set_printoptions(linewidth=18)
        # 断言数组的字符串表示是否与指定的格式化字符串相等
        assert_equal(
            str(a),
            textwrap.dedent("""\
            [2 2 2 2 2 2 2 2
             2 2 2 2 2 2 2 2
             2 2]""")
        )
        # 修改打印选项,限制每行字符数为18,使用1.13版的遗留模式
        np.set_printoptions(linewidth=18, legacy='1.13')
        # 再次断言数组的字符串表示是否符合新的格式化字符串
        assert_equal(
            str(a),
            textwrap.dedent("""\
            [2 2 2 2 2 2 2 2 2
             2 2 2 2 2 2 2 2 2]""")
        )

    def test_edgeitems(self):
        # 设置打印选项,仅显示第一维的第一个元素和阈值以内的元素
        np.set_printoptions(edgeitems=1, threshold=1)
        # 创建一个形状为(3, 3, 3)的NumPy数组,填充从0到26的数值
        a = np.arange(27).reshape((3, 3, 3))
        # 断言数组的字符串表示是否与指定的格式化字符串相等
        assert_equal(
            repr(a),
            textwrap.dedent("""\
            array([[[ 0, ...,  2],
                    ...,
                    [ 6, ...,  8]],

                   ...,

                   [[18, ..., 20],
                    ...,
                    [24, ..., 26]]])""")
        )

        # 创建一个形状为(3, 3, 1, 1)的全零NumPy数组
        b = np.zeros((3, 3, 1, 1))
        # 断言数组的字符串表示是否与指定的格式化字符串相等
        assert_equal(
            repr(b),
            textwrap.dedent("""\
            array([[[[0.]],

                    ...,

                    [[0.]]],


                   ...,


                   [[[0.]],

                    ...,

                    [[0.]]]])""")
        )

        # 修改打印选项,使用1.13版的遗留模式
        np.set_printoptions(legacy='1.13')

        # 再次断言数组的字符串表示是否符合新的格式化字符串
        assert_equal(
            repr(a),
            textwrap.dedent("""\
            array([[[ 0, ...,  2],
                    ..., 
                    [ 6, ...,  8]],

                   ..., 
                   [[18, ..., 20],
                    ..., 
                    [24, ..., 26]]])""")
        )

        # 再次断言数组的字符串表示是否符合新的格式化字符串
        assert_equal(
            repr(b),
            textwrap.dedent("""\
            array([[[[ 0.]],

                    ..., 
                    [[ 0.]]],


                   ..., 
                   [[[ 0.]],

                    ..., 
                    [[ 0.]]]])""")
        )
    # 定义一个测试方法,用于测试在设置特定打印选项后,结构化数组的表示是否正确
    def test_edgeitems_structured(self):
        # 设置打印选项,仅显示边缘元素,超过阈值的元素用省略号表示
        np.set_printoptions(edgeitems=1, threshold=1)
        # 创建一个结构化数组 A,包含从 0 到 29 的整数,形状为 (5, 2, 3)
        A = np.arange(5*2*3, dtype="<i8").view([('i', "<i8", (5, 2, 3))])
        # 预期的结构化数组 A 的字符串表示
        reprA = (
            "array([([[[ 0, ...,  2], [ 3, ...,  5]], ..., "
            "[[24, ..., 26], [27, ..., 29]]],)],\n"
            "      dtype=[('i', '<i8', (5, 2, 3))])"
        )
        # 断言结构化数组 A 的字符串表示是否与预期的 reprA 相等
        assert_equal(repr(A), reprA)

    # 定义一个测试方法,用于测试设置不正确参数时是否会引发异常
    def test_bad_args(self):
        # 断言设置 NaN 作为阈值时会引发 ValueError 异常
        assert_raises(ValueError, np.set_printoptions, threshold=float('nan'))
        # 断言设置字符串 '1' 作为阈值时会引发 TypeError 异常
        assert_raises(TypeError, np.set_printoptions, threshold='1')
        # 断言设置字节串 b'1' 作为阈值时会引发 TypeError 异常
        assert_raises(TypeError, np.set_printoptions, threshold=b'1')

        # 断言设置字符串 '1' 作为精度时会引发 TypeError 异常
        assert_raises(TypeError, np.set_printoptions, precision='1')
        # 断言设置浮点数 1.5 作为精度时会引发 TypeError 异常
        assert_raises(TypeError, np.set_printoptions, precision=1.5)
def test_unicode_object_array():
    # 预期的字符串表示形式
    expected = "array(['é'], dtype=object)"
    # 创建包含一个 Unicode 对象的 NumPy 数组
    x = np.array(['\xe9'], dtype=object)
    # 断言数组的字符串表示形式与预期相符
    assert_equal(repr(x), expected)


class TestContextManager:
    def test_ctx_mgr(self):
        # 测试上下文管理器是否正常工作
        with np.printoptions(precision=2):
            s = str(np.array([2.0]) / 3)
        # 断言计算结果的字符串表示形式是否正确
        assert_equal(s, '[0.67]')

    def test_ctx_mgr_restores(self):
        # 测试打印选项是否被正确还原
        opts = np.get_printoptions()
        with np.printoptions(precision=opts['precision'] - 1,
                             linewidth=opts['linewidth'] - 4):
            pass
        # 断言打印选项是否被恢复到初始状态
        assert_equal(np.get_printoptions(), opts)

    def test_ctx_mgr_exceptions(self):
        # 测试即使出现异常,打印选项也能正确还原
        opts = np.get_printoptions()
        try:
            with np.printoptions(precision=2, linewidth=11):
                raise ValueError
        except ValueError:
            pass
        # 断言打印选项是否被恢复到初始状态
        assert_equal(np.get_printoptions(), opts)

    def test_ctx_mgr_as_smth(self):
        # 测试上下文管理器作为某个对象的行为
        opts = {"precision": 2}
        with np.printoptions(**opts) as ctx:
            saved_opts = ctx.copy()
        # 断言保存的选项是否与预期一致
        assert_equal({k: saved_opts[k] for k in opts}, opts)


@pytest.mark.parametrize("dtype", "bhilqpBHILQPefdgFDG")
@pytest.mark.parametrize("value", [0, 1])
def test_scalar_repr_numbers(dtype, value):
    # 测试数值类型的 NEP 51 标量表示(和旧选项)
    dtype = np.dtype(dtype)
    scalar = np.array(value, dtype=dtype)[()]
    # 断言标量是否为 NumPy 的通用类型
    assert isinstance(scalar, np.generic)

    string = str(scalar)
    repr_string = string.strip("()")  # 复数类型可能有额外的括号
    representation = repr(scalar)
    if dtype.char == "g":
        assert representation == f"np.longdouble('{repr_string}')"
    elif dtype.char == 'G':
        assert representation == f"np.clongdouble('{repr_string}')"
    else:
        normalized_name = np.dtype(f"{dtype.kind}{dtype.itemsize}").type.__name__
        assert representation == f"np.{normalized_name}({repr_string})"

    with np.printoptions(legacy="1.25"):
        assert repr(scalar) == string


@pytest.mark.parametrize("scalar, legacy_repr, representation", [
        (np.True_, "True", "np.True_"),
        (np.bytes_(b'a'), "b'a'", "np.bytes_(b'a')"),
        (np.str_('a'), "'a'", "np.str_('a')"),
        (np.datetime64("2012"),
            "numpy.datetime64('2012')", "np.datetime64('2012')"),
        (np.timedelta64(1), "numpy.timedelta64(1)", "np.timedelta64(1)"),
        (np.void((True, 2), dtype="?,<i8"),
            "(True, 2)",
            "np.void((True, 2), dtype=[('f0', '?'), ('f1', '<i8')])"),
        (np.void((1, 2), dtype="<f8,>f4"),
            "(1., 2.)",
            "np.void((1.0, 2.0), dtype=[('f0', '<f8'), ('f1', '>f4')])"),
        (np.void(b'a'), r"void(b'\x61')", r"np.void(b'\x61')"),
    ])
def test_scalar_repr_special(scalar, legacy_repr, representation):
    # 测试特殊标量类型的字符串表示
    # 测试 NEP 51 标量的字符串表示形式(包括旧版选项)适用于数值类型
    assert repr(scalar) == representation
    # 使用旧版打印选项设置为 "1.25",再次确认 NEP 51 标量的字符串表示形式
    with np.printoptions(legacy="1.25"):
        assert repr(scalar) == legacy_repr
# 定义一个测试函数,用于测试标量、空值、浮点数和字符串的处理
def test_scalar_void_float_str():
    # 创建一个 NumPy 的 void 类型对象 scalar,其内容为 (1.0, 2.0)
    # 使用 dtype 指定了数据类型为包含两个字段的结构化数组:
    # - 'f0' 字段为小端格式的 64 位浮点数
    # - 'f1' 字段为大端格式的 32 位浮点数
    scalar = np.void((1.0, 2.0), dtype=[('f0', '<f8'), ('f1', '>f4')])
    # 断言将该标量对象转换为字符串后结果应为 "(1.0, 2.0)"
    assert str(scalar) == "(1.0, 2.0)"